Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

This course teaches 3D design and digital fabrication using a fully accessible, command-line-driven toolchain centered on OpenSCAD (text-based CAD), 3DMake (non-visual build automation), and accessible editors (VS Code, Notepad++, command-line editors) with screen reader support.

The curriculum is explicitly designed for blind and visually impaired learners who use screen readers (NVDA, JAWS, Orca, VoiceOver). It eliminates GUI navigation and visual feedback in favor of keyboard-driven, text-based workflows that screen readers can fully access. Accessibility is not an add-on. It is the foundation of every tool, workflow, and lesson in this curriculum.

Curriculum Structure

Screen Reader Setup & Accessibility Fundamentals

Before choosing a command-line pathway, students learn to optimize their screen reader setup for terminal work and understand accessibility options.

What’s Included:

Why start here? Screen reader optimization is the foundation for all command-line work. Students learn keyboard shortcuts, navigation techniques, and terminal-specific accessibility before diving into any CLI pathway.

Command-Line Foundation (Choose Your Path)

Students master terminal/command-line fundamentals before learning 3D design. You choose between three equivalent pathways based on your operating system and learning preferences.

Compare All Three Pathways

Command Line Interface Selection Guide

This guide provides a comprehensive comparison including:

  • Feature matrix comparing all three shells
  • Command comparison table (navigation, file operations, scripting)
  • Learner profiles to help you choose
  • Goal-based recommendations
  • FAQ addressing common questions

Where to Start: PowerShell Curriculum Overview

Lessons Included:

  • Powershell Lesson Pre: Your First Terminal - Opening PowerShell, first commands, screen reader tricks
  • Powershell Lesson 0: Getting Started - Paths, shortcuts, tab completion
  • Powershell Lesson 1: Navigation - Moving around the file system confidently
  • Powershell Lesson 2: File and Folder Manipulation - Creating, editing, moving files
  • Powershell Lesson 3: Input, Output, and Piping - Redirecting output, piping commands
  • Powershell Lesson 4: Environment Variables and Aliases - Setting variables, creating shortcuts
  • Powershell Lesson 5: Filling in the Gaps - Control flow, profiles, useful tricks
  • Powershell Lesson 6: Advanced Terminal Techniques - Scripts, functions, professional workflows
  • PowerShell Unit Test & Practice - Comprehensive self-assessment

Time commitment: 30-45 hours (for screen reader users) Best for: Users who want modern Windows features and advanced automation Skills: Terminal navigation, piping, advanced scripting, professional automation

Windows Command Prompt Foundation (Simplified Alternative)

Where to Start: CMD Curriculum Overview

Lessons Included:

  • Command Line Lesson Pre: Your First Terminal - Opening CMD, first commands, screen reader tricks
  • Command Line Lesson 0: Getting Started - Paths, shortcuts, command basics
  • Command Line Lesson 1: Navigation - Moving around the file system confidently
  • Command Line Lesson 2: File and Folder Manipulation - Creating, editing, moving files
  • Command Line Lesson 3: Input, Output & Redirection - Redirecting output, piping commands
  • Command Line Lesson 4: Environment Variables & Shortcuts - Setting variables, shortcuts
  • Command Line Lesson 5: Filling in the Gaps - Batch files, advanced techniques
  • Command Line Lesson 6: Advanced Terminal Techniques - Scripts, automation, professional workflows
  • CMD Unit Test & Practice - Comprehensive self-assessment

Time commitment: 30-45 hours (for screen reader users) Best for: Absolute beginners or users who prefer simplicity Skills: Terminal navigation, file operations, batch scripting, basic automation

Git Bash Foundation (Cross-Platform Skills)

Where to Start: Git Bash Curriculum Overview

Introductory & Reference Materials:

Lessons Included:

  • Bash Lesson Pre: Your First Terminal - Opening Git Bash, first commands, screen reader tricks
  • Bash Lesson 0: Getting Started - Paths, shortcuts, Unix path notation
  • Bash Lesson 1: Navigation - Moving around the file system confidently
  • Bash Lesson 2: File and Folder Manipulation - Creating, editing, moving files
  • Bash Lesson 3: Input, Output & Piping - Redirecting output, piping commands
  • Bash Lesson 4: Environment Variables & Aliases - Setting variables, creating shortcuts
  • Bash Lesson 5: Filling in the Gaps - Shell profiles, history, debugging
  • Bash Lesson 6: Advanced Terminal Techniques - Scripts, functions, professional workflows
  • GitBash Unit Test & Practice - Comprehensive self-assessment

Time commitment: 30-45 hours (for screen reader users) Best for: Users who want cross-platform skills (Windows, macOS, Linux) Skills: Unix/bash commands, shell scripting, cross-platform automation

Important

Choose ONE pathway and complete it fully. All three teach identical fundamental concepts using different tools. Each integrates fully with 3D design workflows.

3dMake Foundation & Design (11 Lessons + 6 Appendices)

Where to Start: 3dMake Introduction

Students build parametric 3D designs using OpenSCAD and automate the workflow with 3DMake.

Main Curriculum: 11 Progressive Lessons

PartLessonsFocusDuration
Foundations1-3Environment setup, primitives, parametric design + advanced language features4-5 hours
Verification & Safety4-5AI verification, safety protocols, materials2-3 hours
Applied Projects6-8Practical commands, text functions, transforms, assembly patterns5-6 hours
Advanced Topics9-10Automation with file I/O, troubleshooting, mastery3-4 hours
Leadership11Stakeholder-centric design2-3 hours

Total: 45-55 hours instruction + practice projects

Reference Appendices

Command Line Tools:

3dMake:

The Accessible Toolchain

Screen Reader Compatibility Throughout

This course uses tools designed for screen reader access:

  • Terminal/Command line - Text-based, fully accessible to NVDA, JAWS, Orca, VoiceOver
  • OpenSCAD - Free, open-source text-based CAD (no visual-only GUI dependency)
  • 3DMake - Command-line build tool eliminating GUI navigation
  • Accessible text editors - Notepad, VS Code, Notepad++, Nano, Vim, etc. (all keyboard-driven, screen reader friendly)

See Appendix A: 3DMake Cheat Sheet for detailed keyboard shortcuts and configuration.

3DMake: Non-Visual Build Automation

3DMake makes the entire design-to-print pipeline accessible:

3dm build        -> Compiles main.scad to main.stl
3dm info         -> Validates geometry and runs diagnostics
3dm slice        -> Prepares model for printing
  • No GUI navigation needed
  • Automation eliminates repetitive manual steps
  • Configuration files store parameters as human-readable text
  • Error reporting is text-based (screen reader accessible)
  • Works with command-line slicers

Iterative, Non-Visual Design

Students learn to design through code and testing, not visual previews:

  • Write parametric OpenSCAD code in accessible editors
  • Run 3dm build to compile to printable file
  • Use measurement-based verification (calipers, scales, functional testing)
  • Iterate by editing parameters and rebuilding
  • No reliance on 3D preview or visual feedback

Project-Based Learning

3dMake lessons include hands-on projects:

  • Lesson 6: Keychain with embossed text (3dm commands)
  • Lesson 7: Phone stand (parametric transforms)
  • Lesson 8: Stackable bins (interlocking features, tolerances)
  • Lesson 9: Build automation (PowerShell batch processing)
  • Lesson 10: QA testing + accessibility audit (measurement, troubleshooting)
  • Lesson 11: Beaded jewelry holder (stakeholder-driven design)

Each project requires:

  • Parametric OpenSCAD code (clean, well-commented)
  • Functional prototype (tested, iterated)
  • Complete documentation (reflections, measurements, decisions)

Learning Support

Primary Navigation & Overview

Curriculum Guide - Detailed overview of all lessons and appendices
Quick Reference - At-a-glance command and syntax reference
mdBook Navigation Guide - How to navigate this curriculum

Setup & Configuration Guides

3dMake Setup Guide - Installation walkthrough
VSCode Setup Guide - Accessibility configuration
Screen Reader Coding Tips (NVDA & JAWS) - Keyboard shortcuts and coding configuration

Quick Reference Materials

OpenSCAD Cheat Sheet - Syntax quick-reference
3DMake CLI Cheat Sheet - Complete 3dm command reference
Filament Comparison Table - Material selection guide
Master Rubric - Project assessment criteria

Safety & Maintenance

Safety Checklist - Pre-print safety procedures
Maintenance Log - Printer maintenance tracking

Troubleshooting & Diagnostics

Common Issues and Solutions - Comprehensive troubleshooting guide
Diagnostic Checklist - Systematic problem diagnosis
Technical Reference - Advanced systems architecture and professional reference

Glossaries & Terminology

Student Glossary - Complete terminology reference for OpenSCAD, 3dMake, 3D Printing, and CLI
Teacher Glossary - Pedagogical framework and instructional design terminology

Command Line Integration Appendices

CLI Appendices Overview - All command line integration guides
Appendix A: CMD/Batch Integration - Windows CMD automation
Appendix B: PowerShell Integration - PowerShell workflow automation
Appendix C: Git Bash Integration - Unix shell integration

3dMake & OpenSCAD Appendices

3dMake Appendices Overview - All 3dMake reference materials
Appendix A: Comprehensive Slicing Guide - PrusaSlicer, Bambu Studio, Cura, OrcaSlicer
Appendix B: Material Properties & Selection Guide - Detailed material specifications
Appendix C: Tolerance Testing & QA Matrix - Quality assurance procedures
Appendix D: Advanced OpenSCAD Concepts - Gears, recursion, performance optimization

Code Examples & Assets

3dMake Code Examples & Assets - OpenSCAD code examples and reference designs

Further Reading & References

References & Further Reading - Peer-reviewed research and scholarly works

Supplemental Resources & Textbooks

Textbook Options

Beginner-Friendly Textbooks:

  • Programming with OpenSCAD: A Beginner’s Guide to Coding 3D-Printable Objects by Justin Gohde and Marius Kintel - Comprehensive reference covering OpenSCAD syntax, geometry concepts, and design patterns. Ideal for deep dives into specific topics and as a reference guide throughout the course. Available in EPUB format (screen reader accessible).
  • Simplifying 3D Printing with OpenSCAD by Alicia Noors - Focused on practical workflows, optimization, and real-world printing scenarios. Available in EPUB/PDF formats.
  • OpenSCAD for 3D Printing by Al Williams - Hands-on introduction to OpenSCAD with practical 3D printing projects. Covers basics through intermediate topics with step-by-step tutorials.
  • Mastering OpenSCAD by Jochen Kerdels - Project-based learning approach with emphasis on parametric design and reusable code modules.

Free Online Resources:

Companion Teaching Resources

Curriculum-Specific Materials:

Practice Worksheets - Printable worksheets for visualization practice, decomposition exercises, vocabulary building, and assessment.
Visual Quick Reference - Command syntax guides and geometry reference.
Code Solutions Repository - Working OpenSCAD examples organized by topic (3D shapes, transformations, loops, modules, if-statements, advanced techniques).

Community Resources:

Getting Started

For Students

Step 1: Screen Reader Setup & Accessibility

Before beginning any technical work, optimize your screen reader configuration for command-line and coding work:

Step 2: Choose Your Command Line Pathway

Read Command Line Interface Selection Guide to compare all three CLI options, then select ONE pathway:

Complete ALL lessons in your chosen pathway (Pre through Lesson 6 + Unit Test) before moving to Step 3.

Step 3: Begin 3dMake Foundation

Once you’ve completed your CLI foundation:

  1. Read 3dMake Introduction - Overview of OpenSCAD and 3dMake
  2. Start Lesson 1: Environmental Configuration - Install OpenSCAD and 3dMake
  3. Progress through Lessons 2-11 sequentially
  4. Complete all project templates as you encounter them
  5. Review 3dMake Foundation Curriculum Guide for detailed lesson descriptions

Step 4: Projects & Documentation

Use the Student Templates for all project documentation:

  • Your First Print (Lesson 1)
  • Your Second Print & Bonus Print (Lesson 2)
  • Dice Dice Dice (Lesson 4)
  • Parametric Keychain (Lesson 6)
  • Miniature Assembly (Lesson 7)
  • Snap Fit Clip (Lesson 8)
  • Accessibility Audit (Lesson 10)
  • Projects 0, 1, and 3 (Lesson 11)

Step 5: Final Assessment

Complete 3dMake Foundation Final Exam to demonstrate mastery of OpenSCAD, 3DMake, and parametric design principles.


For Instructors

Course Setup & Planning:

  1. Review Syllabus - Complete course structure, philosophy, learning objectives, and assessment framework
  2. Read 3dMake Foundation Curriculum Guide - Detailed lesson-by-lesson breakdown with timing and objectives
  3. Study Master Rubric - Comprehensive project assessment criteria
  4. Explore Teacher Glossary - Pedagogical framework and instructional terminology

Assessment Materials:

Use the Teacher Templates for grading and feedback:

  • your_first_print_teacher_template.md
  • your_second_print_teacher_template.md
  • bonus_print_teacher_template.md
  • dice_dice_dice_teacher_template.md
  • parametric_keychain_teacher_template.md
  • miniature_assembly_teacher_template.md
  • snap_fit_clip_teacher_template.md
  • accessibility_audit_teacher_template.md
  • project_0_teacher_template.md
  • project_1_teacher_template.md
  • project_3_teacher_template.md

Final Exam:

Administer 3dMake Foundation Final Exam - 25-question comprehensive assessment covering error detection, code analysis, design challenges, and real-world application (100 points total).

Accessibility Support:

Additional Resources:

Screen Readers

We know that users of this curriculum will primarily be JAWS and NVDA screenreader users, or else users of Orca if on a Linux-based system. Dolphin SuperNova (commercial) and Windows Narrator (built-in) are also supported; the workflows and recommendations in this document apply to them. See https://yourdolphin.com/ScreenReader-Training and https://support.microsoft.com/en-us/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1 for vendor documentation.

3D Design & Printing Curriculum - Non-Visual Toolchain Edition

Author: Michael Ryan Hunsaker, M.Ed., Ph.D.
Last Updated: 2026-03-04

Overview

This curriculum teaches 3D design and digital fabrication using a fully accessible, command-line-driven toolchain centered on OpenSCAD (text-based CAD), 3DMake (non-visual build automation), and accessible editors (VS Code, Notepad++, command-line editors) with screen reader support. Students progress from foundational command-line skills through guided projects to real-world, stakeholder-driven design challenges.

Who This Course Is For

This course is explicitly designed for blind and visually impaired learners who use screen readers (NVDA, JAWS, Orca, VoiceOver, Windows Narrator, Dolphin SuperNova). It eliminates GUI navigation and visual feedback in favor of keyboard-driven, text-based workflows that screen readers can fully access.

Accessibility is not an add-on. It is the foundation of every tool, workflow, and lesson in this curriculum.

Core Philosophy

  1. Text-First Design: All core work happens in text editors and command-line interfaces - no graphical CAD previews, no mouse-dependent menu navigation.

  2. Parametric Thinking: Students learn to express geometry as code using OpenSCAD, enabling precise, reproducible, and iterable designs without visual feedback.

  3. Automation and Independence: 3DMake automates the journey from code to printed object, handling compilation, slicing orchestration, and metadata management through simple command-line commands and text configuration files.

  4. Screen Reader Mastery: Students develop fluency with accessibility technologies (NVDA, JAWS, VoiceOver) and accessible editors, building skills that apply to careers in software, engineering, and digital fabrication.

  5. Real-World Impact: Projects culminate in designing assistive-technology solutions for real stakeholders, combining technical skill with human-centered design and documentation.

Curriculum Structure & Scope/Sequence

Setup & Accessibility Fundamentals (Prerequisite - 2-3 hours)

Start here: Screen Reader Accessibility Guide

Before choosing a command-line pathway, students optimize their screen reader setup for terminal work.

ComponentDurationContent
Screen Reader Accessibility Guide1-1.5 hoursNVDA/JAWS reference for PowerShell, CMD, and Git Bash; keyboard shortcuts
Screen Reader Choice: Windows CLI30 minComparing NVDA, JAWS, Narrator, and Dolphin; choosing the right tool
Braille Display & Terminal Mode30 minOptional: configuring refreshable braille displays for terminal work
Editor Selection and Setup30 minChoosing Notepad, Notepad++, or VS Code; configuring indent announcement

Command-Line Foundation (Choose Your Path)

Start here: Command Line Interface Selection Guide

Students master terminal/command-line fundamentals before learning 3D design. Choose one of three equivalent pathways based on your operating system and preferences. All three pathways teach the same concepts and prepare you equally well for 3dMake work.

Important

Choose ONE pathway and complete it fully. All three teach identical fundamental concepts using different tools. Each integrates fully with 3D design workflows.

Total Duration: 30-45 hours Start here: PowerShell Curriculum Overview

ComponentDurationContent
PowerShell Introduction20-30 minScreen-reader-friendly quick-start (JAWS/NVDA); essential commands overview
PowerShell Tutorial30-45 minHands-on tutorial: paths, navigation, wildcards, running scripts
Powershell Lesson Pre: Your First Terminal2-2.5 hoursOpening PowerShell, first commands, basic navigation, screen reader tricks
Powershell Lesson 0: Getting Started1.5 hoursPaths, shortcuts, tab completion
Powershell Lesson 1: Navigation2-2.5 hoursMoving around the file system confidently
Powershell Lesson 2: File & Folder Manipulation2.5-3 hoursCreating, editing, moving, copying, deleting files and directories
Powershell Lesson 3: Input, Output & Piping2.5-3 hoursRedirecting output, piping commands, understanding data flow
Powershell Lesson 4: Environment Variables & Aliases2-2.5 hoursSetting variables, creating shortcuts, persistent configurations
Powershell Lesson 5: Filling in the Gaps2.5-3 hoursControl flow, profiles, useful tricks, scripting fundamentals
Powershell Lesson 6: Advanced Terminal Techniques4-4.5 hoursScripts, functions, loops, professional workflows, automation patterns
PowerShell Unit Test & Practice2-3 hoursPractice exercises, assessment, reinforcement

Outcomes: Terminal fluency, file system mastery, basic scripting, screen reader optimization, automation readiness

Pathway B: Windows Command Prompt (CMD) (Simpler alternative)

Total Duration: 30-45 hours Start here: CMD Curriculum Overview

ComponentDurationContent
Command Line Lesson Pre: Your First Terminal2-2.5 hoursOpening CMD, first commands, basic navigation, screen reader tricks
Command Line Lesson 0: Getting Started1.5 hoursPaths, shortcuts, command basics
Command Line Lesson 1: Navigation2-2.5 hoursMoving around the file system confidently
Command Line Lesson 2: File & Folder Manipulation2.5-3 hoursCreating, editing, moving, copying, deleting files and directories
Command Line Lesson 3: Input, Output & Redirection2-2.5 hoursRedirecting output, piping commands, understanding data flow
Command Line Lesson 4: Environment Variables & Shortcuts2-2.5 hoursSetting variables, creating shortcuts, persistent configurations
Command Line Lesson 5: Filling in the Gaps2.5-3 hoursBatch files, advanced techniques, scripting fundamentals
Command Line Lesson 6: Advanced Terminal Techniques3-3.5 hoursScripts, automation patterns, professional workflows
CMD Unit Test & Practice2-3 hoursPractice exercises, assessment, reinforcement

Outcomes: Terminal fluency, file system mastery, batch scripting, screen reader optimization, automation readiness

Pathway C: Git Bash (Best for macOS/Linux or cross-platform development)

Total Duration: 20-25 hours Start here: Git Bash Curriculum Overview

ComponentDurationContent
Git Bash Introduction20-30 minScreen-reader-friendly quick-start (JAWS/NVDA); essential commands
Git Bash Tutorial30-45 minHands-on tutorial: paths, navigation, wildcards, running scripts
Screen Reader Accessibility Guide for Git Bash30-45 minNVDA and JAWS configuration specific to Git Bash
Bash Lesson Pre: Your First Terminal2-2.5 hoursOpening Git Bash, first commands, basic navigation, screen reader tricks
Bash Lesson 0: Getting Started1.5 hoursUnix-style paths, shortcuts, command basics, Windows path conversion
Bash Lesson 1: Navigation2-2.5 hoursMoving around the file system confidently
Bash Lesson 2: File and Folder Manipulation2-2.5 hoursCreating, editing, moving, copying, deleting files and directories
Bash Lesson 3: Input, Output & Piping2-2.5 hoursRedirecting output, piping with grep/sort/wc, understanding data flow
Bash Lesson 4: Environment Variables & Aliases1.5-2 hoursSetting variables, creating aliases, editing .bashrc
Bash Lesson 5: Filling in the Gaps2-2.5 hoursShell profiles, command history, debugging
Bash Lesson 6: Advanced Terminal Techniques2.5-3.5 hoursShell scripts, functions, loops, professional workflows
GitBash Unit Test & Practice2-2.5 hoursPractice exercises, assessment, reinforcement

Outcomes: Terminal fluency, file system mastery, bash scripting, version control basics, automation readiness

Common Outcomes (All Pathways)

  • Comfort with terminal/command-line interface
  • File system navigation and manipulation
  • Basic scripting and automation
  • Screen reader optimization for terminal work
  • Foundation for 3DMake automation tasks

3dMake Foundation (Main Curriculum - 16-20 hours)

Start here: 3dMake Introduction

11 progressive lessons building from foundational concepts to leadership-level design thinking, organized in 5 parts. Version 2.1 adds comprehensive advanced programming and design topics throughout.

Foundations (Lessons 1-3 | ~4-5 hours)

LessonFocusDurationProject
Lesson 1Environmental Configuration + Code Documentation Standards60-90 minNone
Lesson 2Primitives & Boolean Operations + Modifier Characters Debugging75-90 minNone
Lesson 3Parametric Architecture + Advanced Programming Concepts90-120 minNone

Verification & Safety (Lessons 4-5 | ~2 hours)

LessonFocusDurationProject
Lesson 4AI-Enhanced Verification & Feedback45-60 minNone
Lesson 5Safety Protocols & Material Introduction60-90 minNone

Applied Projects (Lessons 6-8 | ~5-6 hours)

LessonFocusDurationProject
Lesson 6Practical 3dm Commands + String Functions75-105 minCustomizable Keycap
Lesson 7Parametric Transforms + Math Functions90-120 minPhone Stand
Lesson 8Advanced Design + Assembly Best Practices105-150 minStackable Bins

Advanced Topics (Lessons 9-10 | ~3-4 hours)

LessonFocusDurationProject
Lesson 9Automation + File Import/Export (requires CLI Foundation)75-105 minBatch Processing Automation
Lesson 10Troubleshooting & Mastery with Measurement120-150 minQA Testing + Accessibility Audit

Leadership (Lesson 11 | ~2 hours)

LessonFocusDurationProject
Lesson 11Stakeholder-Centric Design & Design Thinking90-120 minBeaded Jewelry Holder

Total: 16-20 hours of instruction + projects

Reference Appendices

Overview Documents

Command Line Integration Appendices

Located in Command_Line_Interface_Selection/:

AppendixTitleUse When
Appendix ACMD/Batch Integration for SCAD WorkflowsAutomating with Windows Command Prompt and batch files
Appendix BPowerShell Integration for SCAD WorkflowsAutomating with PowerShell scripts and advanced workflows
Appendix CGit Bash / POSIX Shell Integration for SCADAutomating with Unix/bash shell scripts for cross-platform

3dMake & OpenSCAD Appendices

Located in 3dMake_Foundation/:

AppendixTitleUse When
3DMake Cheat SheetComplete 3dm CLI ReferenceQuick command lookup, troubleshooting 3dm commands
Appendix AComprehensive Slicing GuideSlicing questions, switching slicers, quality issues
Appendix BMaterial Properties & Selection GuideChoosing material, troubleshooting prints, cost analysis
Appendix CTolerance Testing & Quality Assurance MatrixStarting a project, verifying dimensions, quality issues
Appendix DAdvanced OpenSCAD ConceptsBuilding mechanical systems, optimizing complex models
Code Examples & Assets3dMake Code Examples & AssetsReference designs, working code examples

Project Templates & Assessment Materials

Student Project Templates

Located in 3dMake_Foundation/Templates/Student/, these templates guide students through structured documentation for each project:

  • your_first_print_student_template.md - Lesson 1 extension project
  • your_second_print_student_template.md - Lesson 2 basic parametric design
  • bonus_print_student_template.md - Lesson 2 advanced practice
  • dice_dice_dice_student_template.md - Lesson 4 verification project
  • parametric_keychain_student_template.md - Lesson 6 practical 3dm commands
  • miniature_assembly_student_template.md - Lesson 7 transforms project
  • snap_fit_clip_student_template.md - Lesson 8 assembly design
  • accessibility_audit_student_template.md - Lesson 10 QA testing
  • project_0_student_template.md - Lesson 11 preliminary design
  • project_1_student_template.md - Lesson 11 prototype iteration
  • project_3_student_template.md - Lesson 11 final stakeholder project

Each template includes sections for problem statement, design decisions, code documentation, testing results, measurements, reflections, and iteration notes.

Teacher Assessment Templates

Located in 3dMake_Foundation/Templates/Teacher/, corresponding templates provide grading rubrics and feedback frameworks:

  • your_first_print_teacher_template.md
  • your_second_print_teacher_template.md
  • bonus_print_teacher_template.md
  • dice_dice_dice_teacher_template.md
  • parametric_keychain_teacher_template.md
  • miniature_assembly_teacher_template.md
  • snap_fit_clip_teacher_template.md
  • accessibility_audit_teacher_template.md
  • project_0_teacher_template.md
  • project_1_teacher_template.md
  • project_3_teacher_template.md

Each teacher template includes the 0-9 rubric scoring guide, common issues to watch for, and focus areas for feedback.

Final Assessment

3dMake Foundation Final Exam - Comprehensive 25-question assessment (100 points total) covering:

  • Section 1: Error Detection & Code Analysis (Problems 1-10)
  • Section 2: Design Challenges & Real-World Application (Problems 11-25)

Questions include error identification, code explanation, behavioral analysis, and design problem-solving.

Master Rubric

Master Rubric - Unified assessment framework used across all projects, providing detailed criteria for the three scoring categories (Problem & Solution, Design & Code Quality, Documentation).

Reference Materials for Students & Teachers

Glossaries

  • Student Glossary - Complete terminology reference for OpenSCAD, 3dMake, 3D Printing, and CLI
  • Teacher Glossary - Pedagogical framework, instructional design strategies, assessment concepts, and accessibility terminology

Technical References

  • Technical Reference & Troubleshooting - Advanced systems architecture, OpenSCAD professional modeling reference, 3DMake professional usage, CLI references (CMD, PowerShell, Git Bash), and comprehensive troubleshooting compendium
  • Further Reading & References - Peer-reviewed research and scholarly works supporting curriculum design

Quick References

Learning Progression: Student Roles

Students move through roles across the curriculum:

PhaseRoleCore ToolsFocus
CLI FoundationObserver/LearnerTerminal, command lineCLI fundamentals and keyboard navigation
3dMake Lessons 1-5Observer/LearnerOpenSCAD, 3DMake, editorUsing CLI tools, safety, concepts, measurement
3dMake Lessons 6-8OperatorEditor, OpenSCAD, 3DMake, slicerHands-on practice with structured projects
3dMake Lessons 9-10DesignerFull toolchainParametric design, automation, troubleshooting
3dMake Lesson 11Problem-SolverFull toolchain + documentationStakeholder design, real-world impact

The Accessible Toolchain: How It Works

OpenSCAD - Text-Based 3D Design

OpenSCAD is a free, open-source CAD tool that uses a programming language to describe 3D geometry. Students write code that defines shapes, transforms them, and combines them using Boolean operations.

Why OpenSCAD?

  • Screen reader friendly: All work happens in a text editor; no visual-only 3D preview.
  • Repeatable: Code is version-controlled, documented, and shareable.
  • Parametric: Variables allow students to design once and generate variations by changing numbers.
  • No visual dependency: Students reason about geometry through code structure and testing.

3DMake - The Non-Visual Build Bridge

3DMake is a command-line tool that automates the journey from OpenSCAD code to a printable file:

3dm build
3dm info
3dm slice

Why 3DMake?

  • No GUI navigation: All interaction is keyboard-driven and text-based.
  • Automation: Eliminates repetitive manual steps.
  • Metadata tracking: Configuration files store parameters as human-readable text.
  • Error reporting: Diagnostic output is text that screen readers can read aloud.

Accessible Editors

Students write OpenSCAD code using screen reader-accessible editors:

  • VS Code (Windows, macOS, Linux): Industry-standard with built-in screen reader support
  • Notepad++ (Windows): Lightweight, keyboard-driven, excellent screen reader support
  • Command-line editors (Nano, Vim, Emacs): Full keyboard control, no mouse needed

Prerequisites by Section

SectionPrerequisitesWhat You’ll Learn
SetupNone - start hereScreen reader optimization, editor selection, accessibility setup
CLI FoundationSetupTerminal basics, keyboard navigation, file operations, basic scripting
3dMake Lessons 1-5Setup (CLI Foundation recommended)3D printing concepts, safety, measurement, OpenSCAD basics, debugging
3dMake Lessons 6-8Lessons 1-5Building projects, parametric design, transforms, tolerances
3dMake Lessons 9-10Lessons 6-8 + CLI Foundation requiredAutomation, troubleshooting, advanced measurement and QA
3dMake Lesson 11Lessons 9-10Stakeholder design, real-world prototyping, leadership

Grading Rubric

All projects are scored on a 0-9 scale across three equally weighted categories (3 points each):

CategoryPointsWhat We Measure
Problem & Solution0-3Does the design solve the stated problem? Are all functional requirements met?
Design & Code Quality0-3Is the OpenSCAD code clean, well-commented, and well-structured? Does the print work well? Is there evidence of iteration?
Documentation0-3Are all sections complete? Are reflections thoughtful and specific? Are measurements recorded?

Category 1: Problem & Solution (0-3 points)

ScoreDescription
3The prototype clearly and effectively solves the stated problem. All functional requirements are met. The solution shows evidence of testing against the requirements.
2The prototype mostly meets the problem. Most functional requirements are met. Minor gaps between the design and the requirements.
1The prototype partially addresses the problem. Several functional requirements are not met or were not clearly tested.
0The prototype does not address the stated problem, or no functional requirements were established.

Category 2: Design & Code Quality (0-3 points)

OpenSCAD code is central to this course. We evaluate the clarity, structure, and documentation of your code as much as the print quality.

ScoreDescription
3Code is clean, well-organized, and thoroughly commented. Variables/modules are used appropriately. Print quality is excellent. Design shows original thinking and at least one meaningful iteration.
2Code works but lacks clear structure or comments. Variables are used but could be better named. Print quality is acceptable. Some iteration evident.
1Code is functional but poorly organized. Comments are minimal or missing. Print quality has defects. Little or no iteration.
0Code does not work, is not submitted, or shows no original thinking. Print is not functional.

Category 3: Documentation (0-3 points)

ScoreDescription
3All required sections are present, complete, and specific. Reflections are thoughtful and reference specific decisions, problems encountered, and learning. Photos/measurements are included.
2Most required sections are present. Some sections are vague or missing detail. Reflections show some thought but are brief or generic.
1Documentation is incomplete. Major sections are missing or consist of one-line responses. Reflections are minimal.
0Documentation is not submitted or is essentially empty.

Score Interpretation

Total ScoreInterpretationNext Step
8-9Excellent workMove on to next project
6-7Good work with room for improvementMove on; instructor may suggest revisiting one element
4-5Meets basic expectationsResubmission of specific weak areas recommended
2-3Does not meet expectationsResubmission required
0-1Missing major deliverablesMeet with instructor; create a completion plan

Resubmission Policy

Students may resubmit any project as many times as they need to improve their score. Resubmissions must include a one-paragraph explanation of what was changed and why. The resubmission score replaces the original score.

Core Design Toolchain

OpenSCAD

3DMake

Editors

Screen Reader & Accessibility

Screen Readers

Note: This curriculum is designed to work with all major screen readers. The workflows are tested primarily with NVDA and JAWS but apply to all screen readers listed above.

Accessibility Configuration

Slicing Software

Supplemental Textbooks & Learning Resources

Beginner-Friendly Textbooks:

Free Online Resources:

Curriculum-Specific Resources:

Community Resources:

Local Resources: Utah Makerspaces & Community Printing

Public Library Make Spaces

Salt Lake City Public Library

  • SLC Public Creative Lab - Main Library (Level 1)
    • Hardware: Prusa i3 MK3, LulzBot Taz 5, Elegoo Mars 2 (resin)
    • Pricing: Free for prints under 6 hours; $0.50/hr + material cost otherwise

Salt Lake County Library System

Makerspaces & Community Centers

Make Salt Lake

  • Location: 663 W 100 S, Salt Lake City, UT 84101
  • Website: https://makesaltlake.org/
  • Equipment: Full metal shop, CNC machines, large-scale FDM and resin printing

University of Utah Maker Spaces

Troubleshooting & Getting Help

Quick Reference Materials

Setup & Configuration:

Syntax & Commands:

Materials & Safety:

When You’re Stuck

For Technical Issues:

  1. Check Common Issues and Solutions - Comprehensive troubleshooting guide
  2. Review Diagnostic Checklist - Systematic problem diagnosis
  3. Consult Technical Reference - Advanced systems architecture and professional reference
  4. Post in OpenSCAD Discord or Reddit r/openscad
  5. Visit your local makerspace for hands-on support

For Accessibility Support:

For Design & Concept Questions:

  • Review Student Glossary for terminology clarification
  • Check project-specific guides in lesson folders
  • Consult the Master Rubric for assessment expectations

Setup and Accessibility Fundamentals — Complete Guide

Everything you need to configure an accessible working environment before starting the command-line or 3dMake curriculum. Read these sections in order the first time through; return to individual sections as reference when needed.


Contents

SectionTitle
Part 1: Choosing a Screen ReaderCompare NVDA, JAWS, Windows Narrator, and Dolphin SuperNova for command-line work
Part 2: Screen Reader Accessibility GuideKey commands and terminal strategies for all four screen readers
Part 3: Braille Display SetupConnecting and configuring a braille display with any screen reader
Part 4: Editor Selection and SetupChoosing and configuring VS Code or other editors for accessible OpenSCAD work

Recommended reading order: Part 1 → Part 2 → Part 3 (if applicable) → Part 4. Parts 3 and 4 can be deferred until you need them.


Part 1: Choosing a Screen Reader for Windows Command-Line Work


Screen readers provide speech output and, where supported, braille output that make text-based interfaces accessible to people who are blind or have low vision. In command-line environments they convert terminal text, prompts, and keyboard navigation into audible or tactile feedback so users can work independently in shells such as Windows Terminal, Command Prompt, PowerShell, and Git Bash.

Choosing a screen reader is a personal decision. There is no single reader that is universally better or worse for every user. Preferences depend on workflow, training, budget, and comfort with customization. Each product has genuine strengths and trade-offs. If possible, try the available options and pick what feels most natural for you.


The Four Screen Readers Covered in This Curriculum

NVDA (NonVisual Desktop Access)

NVDA is a free, open-source screen reader developed by NV Access. It is one of the most widely used screen readers in the world.

Advantages:

  • Free to download and use; supported by donations.
  • Actively developed with frequent updates.
  • Excellent support for Windows terminals (Command Prompt, PowerShell, Windows Terminal, Git Bash).
  • Extensible through a rich add-on ecosystem.
  • Strong community support, forums, and troubleshooting resources.
  • Good braille display support via built-in braille drivers and the BRLTTY/LibLouis library.

Disadvantages:

  • Advanced paid support is community-driven rather than available from a commercial vendor helpdesk.
  • Some edge-case compatibility differences compared to commercial readers.

Cost: Free (donations welcomed at https://www.nvaccess.org/).

Trial: Not applicable — NVDA is always free.

Download: https://www.nvaccess.org/download/


JAWS (Job Access With Speech)

JAWS is a commercial screen reader developed by Freedom Scientific (part of Vispero). It is one of the most feature-rich and widely deployed screen readers in enterprise and educational settings.

Advantages:

  • Mature product with decades of development and broad application compatibility.
  • Extensive scripting system allows deep customization for specific applications.
  • Vendor-provided paid support, training, and documentation.
  • Advanced braille display support and configuration.
  • Widely used in workplaces and schools, so shared knowledge base is large.

Disadvantages:

  • Commercial product with significant licensing cost.
  • JAWS demo mode limits session length to approximately 40 minutes before requiring a computer restart or session reset to continue. This can be disruptive during extended practice sessions.
  • Some advanced customization (JAWS scripts) requires a learning curve.

Cost: Commercial. Typical U.S. pricing is several hundred dollars per year for a software maintenance agreement (SMA), or a higher one-time perpetual license fee. Check https://www.freedomscientific.com/products/software/jaws/ for current pricing.

Trial: JAWS offers a time-limited demonstration mode (approximately 40 minutes per session). After the demo period expires, you must restart the computer to continue using JAWS without a license. This applies to the full JAWS installer — there is no separate shorter trial download.

Download: https://www.freedomscientific.com/downloads/jaws/


Windows Narrator

Windows Narrator is Microsoft’s built-in screen reader, included with Windows 10 and Windows 11 at no extra cost. It has improved significantly with recent Windows releases.

Advantages:

  • Already installed on every Windows 10 and Windows 11 computer — no download or installation needed.
  • No cost.
  • Simple to start: press Windows+Ctrl+Enter to toggle Narrator on and off.
  • Reasonable support for Windows Terminal, Command Prompt, and PowerShell.
  • Integrates tightly with Windows accessibility features.

Disadvantages:

  • Fewer customization options than JAWS or NVDA for complex command-line workflows.
  • Braille display support exists but is more limited than dedicated screen readers.
  • Less powerful for advanced scripting, code editing, or rapid navigation in large terminal outputs.
  • Less community documentation for terminal-specific workflows compared to NVDA and JAWS.

Cost: Free (included with Windows).

Trial: Not applicable — Narrator is always available on Windows.

Enable: Settings > Accessibility > Narrator, or press Windows+Ctrl+Enter.


Dolphin SuperNova

Dolphin SuperNova (sometimes referred to as “Dolphin Screen Reader” or simply “SuperNova”) is a commercial product from Dolphin Computer Access. It is available in several editions: Magnifier, Magnifier & Speech, and Screen Reader. The Screen Reader and Magnifier & Speech editions provide full screen reader functionality.

Advantages:

  • Commercial product with vendor support, training options, and documentation.
  • Offers combined magnification and speech in a single product — useful for users with low vision who benefit from both.
  • Good braille display support.
  • Works with Windows terminals (Command Prompt, PowerShell, Windows Terminal).
  • Full-featured 30-day trial license available for evaluation before purchase.

Disadvantages:

  • Commercial licensing cost.
  • Less widely used than NVDA or JAWS, so community resources and third-party documentation are more limited.
  • Configuration for some terminal workflows may require additional setup.

Cost: Commercial. Pricing varies by edition (Magnifier only, Magnifier & Speech, or Screen Reader). Check https://yourdolphin.com/supernova/ for current pricing. Expect costs broadly similar to other commercial screen readers.

Trial: Dolphin provides a full-featured 30-day trial license. This is more generous than JAWS’s per-session demo and allows uninterrupted evaluation over a full month.

Download: https://yourdolphin.com/supernova/


Choosing Between Them for Command-Line Work

Use this decision guide to narrow your choice:

If budget is the primary constraint:
Start with NVDA or Windows Narrator. Both are free. NVDA is generally more capable and better documented for terminal work. Windows Narrator requires no installation and is a good quick-start option.

If you already own or have access to JAWS or Dolphin through school or work:
Use what you have. Both work well for this curriculum.

If you have low vision (partial sight) in addition to using a screen reader:
Consider Dolphin SuperNova, which combines magnification and speech in one product, or use Windows Magnifier alongside NVDA.

If your organization requires vendor-supported software:
JAWS and Dolphin SuperNova both offer commercial support contracts.

If you are unsure:
Install NVDA (free, no risk) and try a few lessons. You can always switch later, and the terminal commands you learn work identically regardless of which screen reader you use.


Terminal Command Reference by Screen Reader

All four screen readers can perform the same tasks in the terminal. The table below shows the key actions and how to perform them with each reader. Exact key names can vary by keyboard layout and screen reader configuration.

TaskNVDAJAWSWindows NarratorDolphin SuperNova
Read current line or promptNVDA+Home (reads current line)Insert+Up Arrow (re-reads current line)Narrator+D (reads current line)CapsLock+L (reads current line)
Read all output from hereNVDA+Down Arrow (read to end of screen)Insert+Ctrl+Down (read to end of screen)Narrator+R (read from cursor)CapsLock+Numpad Plus (say all)
Move to previous line of outputUp Arrow in review modeInsert+Up Arrow (line by line)Narrator+Up Arrow (scan mode)CapsLock+Numpad 8
Move to next line of outputDown Arrow in review modeInsert+Down Arrow (line by line)Narrator+Down Arrow (scan mode)CapsLock+Numpad 2
Jump to end of screen/bufferNVDA+EndInsert+EndNarrator+EndCapsLock+Page Down
Jump to start of screen/bufferNVDA+HomeInsert+HomeNarrator+HomeCapsLock+Page Up
Recall last command (shell history)Up Arrow (shell native; SR reads it)Up Arrow (shell native; SR reads it)Up Arrow (shell native; SR reads it)Up Arrow (shell native; SR reads it)
Stop readingCtrlCtrlCtrlCtrl
Open screen reader settingsNVDA+N > PreferencesInsert+F3 > Options/SettingsWindows+Ctrl+N (Narrator settings)CapsLock+SpaceBar (SuperNova control panel)

Notes on modifier keys:

  • NVDA key is Insert by default; can be changed to CapsLock in NVDA Preferences > Keyboard.
  • JAWS key is Insert by default; can be changed to CapsLock in JAWS Settings Center.
  • Narrator key is CapsLock or Insert; configurable in Settings > Accessibility > Narrator > Keyboard shortcuts.
  • Dolphin key is CapsLock by default; configurable in SuperNova Control Panel > Keyboard.

Important Notes for This Curriculum

  1. All four screen readers work with all three shells (CMD, PowerShell, Git Bash) covered in this curriculum. You do not need to change screen readers based on which shell pathway you choose.

  2. The best practice for all four screen readers when dealing with long terminal output is to redirect it to a file and open it in Notepad:

    command > output.txt
    notepad output.txt
    

    This works in CMD, PowerShell, and Git Bash, and gives you a stable document that all four screen readers can read comfortably.

  3. Braille display users can use a braille display alongside any of these four screen readers. See the Braille Display Setup guide for detailed instructions.

  4. The screen reader tips in each lesson of this curriculum are written for NVDA, JAWS, Windows Narrator, and Dolphin SuperNova. If the specific key commands differ from what you hear when practicing, check your screen reader’s documentation for the equivalent command — the underlying concept is always the same.


Additional Resources


Part 2: Screen Reader Accessibility Guide for Command-Line Terminals


Target Users: NVDA, JAWS, Windows Narrator, and Dolphin SuperNova users using PowerShell, CMD, or Git Bash
Last Updated: February 2026

This guide is used throughout the Command-Line Foundation curriculum (PowerShell, CMD, and Git Bash pathways) to help screen reader users navigate and work efficiently with the terminal.


Table of Contents

  1. Which Terminal Should I Use?
  2. Getting Started with Screen Readers
  3. NVDA-Specific Tips
  4. JAWS-Specific Tips
  5. Windows Narrator-Specific Tips
  6. Dolphin SuperNova-Specific Tips
  7. General Terminal Accessibility
  8. Working with Long Output
  9. Keyboard Shortcuts Reference
  10. Shell-Specific Differences
  11. Troubleshooting

Which Terminal Should I Use?

All three command-line shells (PowerShell, CMD, Git Bash) work well with screen readers. Choose the one that best fits your setup:

FeaturePowerShellCMDGit Bash
PlatformWindows onlyWindows onlyWindows, macOS, Linux
Screen Reader SupportExcellentExcellentExcellent
Learning CurveModerateGentleModerate-Steep
Use CaseModern automationFamiliar simplicityCross-platform/Git workflows
Recommended For3D design automationGetting started easilySoftware developers

Key Point: Choose one pathway and complete it fully. All three teach the same skills and prepare you equally well for 3dMake work. Don’t switch mid-curriculum.


Getting Started with Screen Readers

Which Screen Reader Should I Use?

NVDA, JAWS, Windows Narrator, and Dolphin SuperNova all work with the three shells covered in this curriculum. Here is a brief comparison:

FeatureNVDAJAWSWindows NarratorDolphin SuperNova
CostFree (open-source)Commercial (paid)Free (built into Windows)Commercial (paid)
InstallationSimple downloadComplex but thoroughAlready installedStandard installer
Terminal SupportExcellent (all shells)Excellent (all shells)Good (all shells)Good (all shells)
Learning CurveGentleSteeperMinimalModerate
CustomizationGood (add-ons)Extensive (scripts)LimitedGood

Recommendation: If you are new to screen readers, start with NVDA (free, well-documented, good community support) or Windows Narrator (already on your computer, no installation needed). JAWS and Dolphin SuperNova are excellent choices if you already own a license or your organization provides one.

Before You Start

  1. Make sure your screen reader is running before opening your terminal.
  2. Open your terminal (PowerShell, CMD, or Git Bash) and let your screen reader read the title and prompt.
  3. If you do not hear anything, press Alt+Tab to cycle windows and find your terminal.
  4. Use your screen reader’s review/virtual cursor to understand the layout.

NVDA-Specific Tips

NVDA is free and available from https://www.nvaccess.org/

These tips work across all shells: PowerShell, CMD, and Git Bash.

Key Commands for Terminals

CommandWhat It Does
NVDA+HomeRead the current line (your command or output)
NVDA+Down ArrowRead from cursor position to end of screen
NVDA+Up ArrowRead from top of screen to cursor
NVDA+Page DownRead next page
NVDA+Page UpRead previous page
NVDA+F7Open the Elements List / Review Mode viewer
NVDA+Shift+Right ArrowRead next word
NVDA+Shift+Down ArrowRead entire visible screen
NVDA+EndJump to end of line
NVDA+HomeJump to start of line
NVDA+Numpad 5Announce the character under the review cursor
NVDA+Shift+Numpad 5Announce the word under the review cursor

Note on NVDA key: On desktop keyboards the NVDA modifier is typically the Insert key. On laptops without a numpad the NVDA key is often CapsLock. You can change this in NVDA Preferences > Keyboard.

Example: Reading Long Output

Scenario: You ran a command and it listed 50 files. You cannot hear them all at once.

Solution with NVDA:

  1. After the command finishes, press NVDA+Home to read the current line.
  2. Press NVDA+Down Arrow repeatedly to read all output line by line.
  3. Or redirect to a file first: command > output.txt, then open with notepad output.txt for more comfortable reading.

NVDA Settings for Terminals

  1. Press NVDA+N to open the NVDA menu.
  2. Go to Preferences > Settings > Speech.
  3. Increase or decrease verbosity to taste.
  4. Under Document Formatting, enable “Report indentation” (important for reading code).
  5. Under Terminal, enable “Speak typed characters” so you hear each key as you type.

JAWS-Specific Tips

JAWS is a commercial screen reader available from https://www.freedomscientific.com/products/software/jaws/

These tips work across all shells: PowerShell, CMD, and Git Bash.

Key Commands for Terminals

CommandWhat It Does
Insert+Down ArrowRead all / say all from cursor downward
Insert+Up ArrowRe-read current line
Insert+Page DownRead next page of terminal output
Insert+Page UpRead previous page of terminal output
Insert+EndJump to end of text on screen
Insert+HomeJump to start of text on screen
Insert+Ctrl+DownRead to end of screen
Insert+Ctrl+UpRead to beginning of screen
Insert+Shift+Page DownSelect and read next page
Insert+F3Open JAWS menu
Insert+ZToggle JAWS virtual cursor on/off
Insert+F2Open JAWS Manager (Settings Center)

Note on JAWS key: The JAWS modifier is typically Insert on a standard keyboard. On laptops, JAWS can be configured to use CapsLock as the modifier instead.

Example: Reading Long Output

Scenario: You ran a command and saved output to a file.

Solution with JAWS:

  1. Open the file in Notepad: notepad file.txt
  2. In Notepad, press Insert+Ctrl+Down to hear all content from the top.
  3. Use Insert+Down Arrow to read line by line at your own pace.
  4. Use Insert+F (JAWS Find) to search for specific text within the file.

JAWS Settings for Terminals

  1. Press Insert+F3 to open the JAWS menu.
  2. Go to Options > Settings Center (or Utilities > Settings Manager in older versions).
  3. Search for “terminal” or “console”.
  4. Enable “Announce output” and verify “Speak when program speaks” is on.
  5. For indent reporting, search for “Indent” and set to “Tones” or “Tones and Speech”.

Windows Narrator-Specific Tips

Windows Narrator is built into Windows 10 and Windows 11 at no extra cost. Enable it via Settings > Accessibility > Narrator or press Windows+Ctrl+Enter.

These tips work across all shells: PowerShell, CMD, and Git Bash.

Key Commands for Terminals

CommandWhat It Does
Narrator+DRead current line
Narrator+MRead next line
Narrator+IRead current item or focused element
Narrator+RRead from cursor / read all from here
Narrator+Ctrl+RRead page / read all
Narrator+Left/Right ArrowMove to previous/next item
Narrator+Up/Down ArrowMove to previous/next line in scan mode
Narrator+EnterActivate/interact with current item
Narrator+SpaceToggle Narrator scan mode (browse vs. type mode)
Narrator+F1Open Narrator help
Windows+Ctrl+EnterStart or stop Narrator

Note on Narrator key: The Narrator modifier is CapsLock or Insert by default. You can change this in Settings > Accessibility > Narrator > Keyboard shortcuts.

Working with Terminals Using Narrator

Narrator works well in focus mode (the default when a terminal is active). In focus mode, arrow keys move through command history and output rather than triggering Narrator navigation.

Tips:

  • After running a command, press Narrator+D to read the current line.
  • Use Narrator+R to read all output from the current position.
  • For long outputs, always redirect to a file: command > output.txt, then open in Notepad where Narrator’s reading experience is more comfortable.
  • In Windows Terminal, enable “Accessible terminal” mode in Windows Terminal settings for better Narrator integration.

Narrator Settings for Terminals

  1. Open Settings > Accessibility > Narrator.
  2. Under “Change what you hear when typing”, enable “Hear characters as you type”.
  3. Under “Change what Narrator reads”, enable “Read hints for controls and buttons”.
  4. Set verbosity level to 3 or 4 for a good balance of detail.
  5. Under “Choose a Narrator voice”, select a voice you find comfortable for extended use.

Known limitation: Narrator has fewer customization options than JAWS or NVDA for advanced terminal work. If you find Narrator insufficient for complex workflows, consider switching to NVDA (free) or JAWS.


Dolphin SuperNova-Specific Tips

Dolphin SuperNova is a commercial screen reader (with optional magnification) available from https://yourdolphin.com/supernova/

These tips work across all shells: PowerShell, CMD, and Git Bash.

Key Commands for Terminals

CommandWhat It Does
Caps Lock+Down Arrow (or NumPad 2)Read current line
Caps Lock+Numpad 5Read current word
Caps Lock+Numpad 6Read next word
Caps Lock+Numpad 4Read previous word
Caps Lock+Numpad 8Read from cursor to top
Caps Lock+Numpad 2Read from cursor to bottom
Caps Lock+Numpad PlusSay all / read all from current position
Caps Lock+LRe-read current line
Caps Lock+Right ArrowRead next character
Caps Lock+Left ArrowRead previous character
Caps Lock+Page DownJump to end of document or screen
Caps Lock+Page UpJump to start of document or screen

Note on Dolphin key: Dolphin SuperNova typically uses Caps Lock as its modifier key (referred to as the “Dolphin key”). This can be changed in SuperNova Control Panel > Keyboard.

Working with Terminals Using Dolphin SuperNova

  1. Open SuperNova before opening your terminal application.
  2. Dolphin SuperNova automatically tracks focus as you move between the editor, terminal, and file explorer.
  3. In the terminal, use the Dolphin key+Numpad Plus (say all) to have the screen read after running a command.
  4. For complex output, redirect to a file and open in Notepad: command > output.txt, then notepad output.txt.

Dolphin SuperNova Settings for Terminals

  1. Open SuperNova Control Panel (press Caps Lock+SpaceBar, or click the SuperNova icon).
  2. Go to Speech > Verbosity and set a comfortable level (3 or 4 recommended for terminal work).
  3. Go to Speech > Text Processing > Indentation and enable indentation announcement (important for code).
  4. Go to Braille > Settings if you are using a braille display alongside speech.
  5. In General > Application Settings, you can set terminal-specific verbosity so SuperNova behaves differently in your terminal versus other programs.

Note: Dolphin SuperNova’s magnification features can be helpful if you have some remaining vision. Terminal text can be magnified while still receiving speech output.


General Terminal Accessibility

Understanding the Terminal Layout

All terminals (PowerShell, CMD, Git Bash) follow the same basic layout:

  1. Title bar: Window name (e.g., “Windows PowerShell”, “Command Prompt”, “Git Bash”)
  2. Content area: Command history and output
  3. Prompt: The area where you type (e.g., PS>, C:\>, $)

Your screen reader reads from top to bottom, but focus is at the prompt (bottom).

When you open any terminal:

  1. Your screen reader announces the window title.
  2. Then it announces the prompt line.
  3. Anything before the prompt is previous output.
  4. Anything after the prompt is where new output will appear.

Reading Output Effectively

Strategy 1: Immediate Output (Small Amount)

  • Run a command.
  • Your screen reader announces output immediately.
  • This works well for short outputs (a few lines).

Strategy 2: Large Output (Many Lines)

  • Redirect to a file: command > output.txt
  • Open the file: notepad output.txt (works in all shells on Windows)
  • Read in Notepad — easier and more controllable for all screen readers.

Strategy 3: Filtering Output

  • Use filtering commands to reduce output.
  • PowerShell: command | Select-String "pattern"
  • CMD: command | find "pattern"
  • Git Bash: command | grep "pattern"

Working with Long Output

This is one of the most common challenges for screen reader users. Here are proven solutions:

command > output.txt
notepad output.txt

Advantages: Easy to navigate at your own pace, works with all screen readers, output does not scroll away, you can save it for later reference.

Solution 2: Use Pagination

command | more

Press Space to see the next page, Q to quit. Note: some screen readers struggle with more; Solution 1 is generally preferred.

Solution 3: Filter Output

# PowerShell
ls | Select-String "\.scad"

# CMD
dir | find ".scad"

# Git Bash
ls -la | grep ".scad"

Solution 4: Count Before Displaying

# PowerShell
(ls).Count

This tells you how many items there are before deciding whether to redirect to a file.


Keyboard Shortcuts Reference

Shell Navigation (Works Regardless of Screen Reader)

KeyActionWhy It Matters
Up ArrowShow previous commandRepeat commands without retyping
Down ArrowShow next commandNavigate through history
TabAuto-complete path or command nameFaster and more accurate
Shift+TabCycle backward through completionsIf Tab went too far
HomeJump to start of command lineEdit beginning of a command
EndJump to end of command lineEdit end of a command
Ctrl+ASelect all text on lineCopy entire command
Ctrl+CStop / interrupt running commandAbort long-running tasks
Ctrl+LClear screenStart fresh visually
EnterRun commandExecute what you typed

Screen Reader Navigation Quick Reference

TaskNVDAJAWSWindows NarratorDolphin SuperNova
Read current lineNVDA+HomeInsert+Up ArrowNarrator+DCapsLock+L
Read all from hereNVDA+Down ArrowInsert+Ctrl+DownNarrator+RCapsLock+Numpad Plus
Read next lineDown Arrow (review)Insert+Down ArrowNarrator+MCapsLock+Numpad 2
Read previous lineUp Arrow (review)Insert+Up ArrowNarrator+Up ArrowCapsLock+Numpad 8
Jump to end of outputNVDA+EndInsert+EndNarrator+EndCapsLock+Page Down
Jump to start of outputNVDA+HomeInsert+HomeNarrator+HomeCapsLock+Page Up
Stop readingCtrlCtrlCtrlCtrl

Shell-Specific Differences

While all three shells work equally well with screen readers, there are differences in commands and syntax:

File Listing and Navigation

TaskPowerShellCMDGit Bash
List filesls or Get-ChildItemdirls -la
List names onlyls -Namedir /Bls -1
Change directorycd pathcd pathcd path
Current locationpwdcd (no args)pwd
Create foldermkdir foldernamemkdir foldernamemkdir foldername
Delete fileRemove-Item file.txtdel file.txtrm file.txt
Home directory$HOME or ~%USERPROFILE%~

Output Redirection

TaskPowerShellCMDGit Bash
Save to filecommand > file.txtcommand > file.txtcommand > file.txt
Append to filecommand >> file.txtcommand >> file.txtcommand >> file.txt
Filter outputcommand | Select-String "text"command | find "text"command | grep "text"
Open filenotepad file.txtnotepad file.txtnotepad file.txt (Windows)

Scripting and Automation

FeaturePowerShellCMDGit Bash
File extension.ps1.bat.sh
Comment#REM or ::#
Variable$var = "value"set var=valuevar=value
Echo textWrite-Host "text"echo textecho text
Get helpGet-Help commandhelp commandman command

Choose ONE pathway and stick with it. Each curriculum teaches you the concepts using that specific shell’s syntax. The accessibility experience is virtually identical across all four screen readers in all three shells — only the command syntax differs.


Troubleshooting

Problem 1: “I Can’t Hear the Output After Running a Command”

Causes and Solutions:

  1. Cursor is not at the prompt — Press End or Ctrl+End to go to the end of text, then use screen reader commands to review.
  2. Output scrolled off-screen — Redirect to file: command > output.txt, then notepad output.txt.
  3. Screen reader focus is on window title, not content — Press Tab or arrow keys to move into the content area.
  4. Large output overwhelming screen reader — Use filtering: command | grep "pattern" (Git Bash), command | find "text" (CMD), or command | Select-String "text" (PowerShell).

Problem 2: “Tab Completion Isn’t Working”

  1. You must type at least one character before pressing Tab.
  2. The folder or file must exist — run dir (CMD), ls (PowerShell/Git Bash) to check.
  3. If multiple matches exist, press Tab again to cycle through them.

Problem 3: “Access Denied or Permission Denied”

  1. Close your terminal, right-click it, and choose Run as administrator. Confirm the UAC prompt.
  2. If the file is in use by another program, close that program and try again.
  3. If the path contains spaces, use quotes: cd "Program Files".

Problem 4: “A Command Runs Forever and Won’t Stop”

Press Ctrl+C to interrupt any running command.

Problem 5: “I Need to Edit My Last Command”

  1. Press Up Arrow to recall the previous command.
  2. Use Left/Right Arrow keys to move through it.
  3. Edit as needed and press Enter to run the modified version.

Problem 6: Screen Reader is Not Announcing Indentation

Proper indent announcement is critical for reading code. Enable it for your screen reader:

  • NVDA: NVDA Menu > Preferences > Settings > Document Formatting > enable “Report indentation”, set to “Tones and speech”.
  • JAWS: Settings Center > search “Indent” > enable “Announce Indentation”, set mode to “Tones” or “Tones and Speech”.
  • Windows Narrator: Settings > Accessibility > Narrator > Advanced Options > enable “Report indentation” (limited options compared to NVDA/JAWS).
  • Dolphin SuperNova: SuperNova Control Panel > Speech > Text Processing > Indentation > enable and set preferred announcement style.

Pro Tips for Efficiency

Create Aliases for Frequently Used Commands

PowerShell: Set-Alias -Name ll -Value "Get-ChildItem -Name"
CMD: Create a .bat file in a folder on your PATH.
Git Bash: alias ll='ls -la' (add to ~/.bashrc to make permanent)

Use Command History

All shells support Up/Down Arrow to navigate history. In PowerShell, history shows a numbered list and Invoke-History 5 reruns command number 5. In Git Bash, history and !5 work similarly.

Redirect Everything to Files for Accessibility

If a command produces output, save it:

command > results.txt
notepad results.txt

This is always more accessible than reading from the terminal directly.


Quick Reference Card

EVERY SESSION STARTS WITH:
1. pwd / cd            (where am I?)
2. dir / ls            (what is here?)
3. cd path             (go there)

LONG OUTPUT?
-> command > file.txt
-> notepad file.txt

STUCK?
-> Ctrl+C

WANT TO REPEAT?
-> Up Arrow

NEED HELP?
-> PowerShell:  `Get-Help command-name`
-> CMD:         `help command-name`
-> Git Bash:    `man command-name`

Additional Resources


Part 3: Using a Braille Display with the Curriculum


Many blind and low-vision programmers prefer tactile output alongside or instead of speech. A refreshable braille display presents terminal text as a row (or multiple rows) of braille cells and allows you to read at your own pace, re-read lines without interrupting speech, and work quietly. This page covers how to connect and configure a braille display with each screen reader used in this curriculum.


How a Braille Display Works with a Terminal

A refreshable braille display uses small pins that rise and fall to form braille characters. When connected to a computer and paired with a screen reader, the display shows the line of text where the screen reader’s focus or review cursor is located. You can pan left and right across a long line or press routing buttons to move the screen reader cursor to a specific position.

In a terminal environment:

  • The display shows the current command line (what you are typing).
  • After running a command, you can use your screen reader’s review cursor and the display’s pan keys to read through the output line by line.
  • Routing keys (small buttons above or below each braille cell) let you move the cursor directly to that point in the text — useful for re-running or editing commands from history.

Connecting a Braille Display

USB Connection

  1. Plug the display’s USB cable into your computer.
  2. Windows will attempt to install drivers automatically. If the display is not recognized, install the vendor’s driver software first (see vendor links at the end of this page).
  3. Open your screen reader’s braille settings and select the connected display.

Bluetooth Connection

  1. Put the braille display into pairing mode (refer to the device’s quick-start guide).
  2. On Windows, go to Settings > Bluetooth & devices > Add a device and pair the display.
  3. Once paired, open your screen reader’s braille settings and select the display.

Before Opening the Terminal

Always confirm the display is connected and showing output before opening your terminal. A quick test: open Notepad, type a few words, and verify they appear on the display. This confirms the screen reader is routing output correctly before you add the complexity of a terminal session.


Configuring Each Screen Reader for Braille

NVDA

NVDA includes built-in braille support for a wide range of displays without requiring separate vendor software for many devices.

  1. Connect your display via USB or Bluetooth.
  2. Open the NVDA menu: press NVDA+N (Insert+N or CapsLock+N depending on your modifier key setting).
  3. Go to Preferences > Settings > Braille (or press NVDA+Ctrl+B as a shortcut on some versions).
  4. In the “Braille display” dropdown, select your display from the list. NVDA supports automatic detection for many displays — you can also select “Automatic” and let NVDA detect it.
  5. Set your preferred braille output table (e.g., Unified English Braille Grade 1 or Grade 2, or your country’s national table).
  6. Set “Braille input table” if you want to type commands using the display’s braille keyboard (if equipped).
  7. Enable “Show cursor” so you can see the caret position on the display.
  8. Click OK and test by moving the cursor in Notepad.

Recommended NVDA braille settings for terminal work:

  • Output table: Unified English Braille Grade 1 (uncontracted) is recommended for reading code — contractions in Grade 2 can make code harder to read.
  • Cursor shape: Dots 7 and 8 (underline) is a common choice.
  • Enable “Word wrap” to avoid cutting words at the display’s edge.

NVDA braille keyboard shortcut reference (while braille display is active):

ActionNVDA Command
Pan braille display rightDisplay’s right pan key
Pan braille display leftDisplay’s left pan key
Toggle braille tethered to focus/reviewNVDA+Ctrl+T
Move to previous braille lineNVDA+Shift+Up (or display key)
Move to next braille lineNVDA+Shift+Down (or display key)
Open braille settingsNVDA+Ctrl+B (some versions)

JAWS

JAWS supports a wide range of braille displays through its built-in braille manager and additional vendor drivers.

  1. Connect your display via USB or Bluetooth.
  2. Install the vendor’s display driver if required (check the vendor’s website — some displays work without a driver in JAWS, others need one).
  3. Open the JAWS menu: press Insert+F3 (or your JAWS key+F3).
  4. Go to Options > Basics > Braille or use the JAWS Settings Center and search for “Braille”.
  5. In Braille Settings, select your display model from the list.
  6. Choose your braille translation table (e.g., English Unified Grade 1 for uncontracted, Grade 2 for contracted).
  7. Configure cursor routing so that pressing a routing button on the display moves the JAWS cursor to that position.
  8. Test in Notepad before moving to a terminal.

JAWS braille settings for terminal work:

  • Use Grade 1 (uncontracted) braille for reading code and terminal output. Grade 2 contractions can make commands and file paths difficult to parse.
  • Enable “Show active cursor” in JAWS braille settings.
  • In the JAWS Settings Center, look for “Braille for Applications” — you can set different braille behavior for specific applications (e.g., a terminal vs. a word processor).

Accessing braille settings:

  • Insert+F3 > Options > Basics > Braille
  • Or: Insert+F2 (JAWS Manager) > Settings Center > search “braille”

Windows Narrator

Windows Narrator supports braille output through the Windows braille service (Windows 10 version 1903 and later, and Windows 11).

  1. Connect your display via USB or Bluetooth.
  2. Install the vendor’s display driver if required.
  3. Open Settings > Accessibility > Narrator > Braille (Windows 11) or Settings > Ease of Access > Narrator > Use Braille (Windows 10).
  4. Turn on “Install braille” (first-time setup may require downloading the braille translation component — approximately 70 MB).
  5. Select your display brand and model from the list.
  6. Choose a braille table (Grade 1 recommended for terminal work).
  7. Test in Notepad before using in a terminal.

Important Narrator braille notes:

  • Narrator’s braille support uses the BRLTTY back-end on Windows, which supports most mainstream displays.
  • If your display is not listed, check for a Windows Update or visit the display vendor’s website for a Windows Narrator-compatible driver.
  • Narrator’s braille customization is less extensive than NVDA’s or JAWS’s. If you need more control, consider using NVDA (free) for braille-heavy work.
  • The braille display showing Narrator output does not change the fact that Narrator’s keyboard commands remain the same — your display shows what Narrator is currently reading.

Dolphin SuperNova

Dolphin SuperNova includes integrated braille support as part of its screen reader editions (SuperNova Magnifier & Speech and SuperNova Screen Reader).

  1. Connect your display via USB or Bluetooth.
  2. Install the vendor’s driver if required.
  3. Open the SuperNova Control Panel: press CapsLock+SpaceBar or click the SuperNova icon in the taskbar.
  4. Go to Braille > Display and select your display model from the list.
  5. Go to Braille > Translation and select your braille table (Grade 1 / uncontracted recommended for code).
  6. Go to Braille > Settings to configure cursor style, word wrap, and other options.
  7. Click Apply and test in Notepad.

Dolphin SuperNova braille tips for terminal work:

  • SuperNova supports a wide range of displays from Freedom Scientific (Focus), HumanWare (Brailliant, BrailleNote as terminal), HIMS, Optelec, and others.
  • Use Grade 1 (uncontracted) braille for terminal and code work.
  • SuperNova’s “Braille cursor tracking” setting determines whether the braille display follows the text cursor or the screen review cursor — set this to “Cursor” when working in a terminal.
  • Dolphin provides a braille viewer on screen (a visual representation of what is on the braille display) — useful when setting up or troubleshooting.

Using the Braille Display in a Terminal

Once your display is configured, here is how to work in a terminal:

  1. Reading the prompt: The display shows your current prompt (e.g., C:\Users\YourName> or PS C:\>). Pan right if the prompt is longer than your display width.
  2. Reading output: After running a command, use your screen reader’s review cursor commands (see the Screen Reader Accessibility Guide) to move through the output. The display shows one line at a time and updates as you move.
  3. Redirecting long output: For long terminal output, redirect to a file and open in Notepad:
    command > output.txt
    notepad output.txt
    
    In Notepad, you can pan through the braille display comfortably without the output scrolling away.
  4. Using routing keys: Press the routing key above a word or character to move your cursor to that position. This is especially useful for editing commands recalled from shell history.

Braille Grade and Code

For all screen readers, use Grade 1 (uncontracted) braille when working in terminals and with code. Contracted braille (Grade 2) uses abbreviations designed for reading prose, and those contractions will make command names, file paths, and code syntax difficult or impossible to read correctly.

Example: In Grade 2, the letters “cd” might be represented as a contraction meaning something other than the Change Directory command. In Grade 1, cd is always shown as the letters c and d.


Notetakers and BrailleNote / BrailleSense Devices

BrailleNote Touch+ (HumanWare) and BrailleSense (HIMS) devices run Android as their primary operating system. They cannot run 3dMake or Windows-based terminal workflows natively. These devices are not supported as standalone authoring environments for this curriculum.

Workaround — using them as braille terminals: Both device families can function as a braille display when connected to a Windows computer via USB or Bluetooth. In that configuration:

  • The device acts as a standard refreshable braille display.
  • Your Windows screen reader (NVDA, JAWS, Narrator, or SuperNova) drives the output.
  • Commands are typed on the Windows keyboard; the BrailleNote/BrailleSense shows the output as braille.

To set this up, refer to your device’s documentation for “Terminal mode” or “PC connection mode” and then follow the screen reader braille configuration steps above for your chosen screen reader.


Multiline Braille Displays

Standard refreshable braille displays show a single line of braille (typically 32, 40, or 80 cells). Multiline displays show several lines simultaneously, which can significantly improve the experience of reading code or terminal output because you can see context above and below the current line.

Examples

Monarch (APH / HumanWare partnership):
A multiline braille device developed by the American Printing House for the Blind (APH) in partnership with HumanWare. It presents multiple lines of braille and supports graphical braille output, making it useful for reviewing blocks of code, diagrams, and structured text. Confirm current driver and screen reader compatibility before purchase.

DotPad (Dot Inc.):
A multiline braille and tactile graphics display. Its multiline capability allows programmers to scan several lines of code or terminal output at once. Useful for reviewing structured output without panning repeatedly. Check current Windows compatibility and screen reader support status.

Graphiti and Graphiti Plus (Orbit Research):
Multiline tactile displays from Orbit Research designed for reading text and tactile graphics. Their expanded line count helps with reading code structure and terminal output. Check current driver support for NVDA, JAWS, Narrator, and SuperNova.

Considerations for Multiline Displays

  • Driver and screen reader support: Multiline displays are newer technology and support varies. Confirm that your chosen screen reader (NVDA, JAWS, Narrator, or SuperNova) has a driver for the specific device before purchase.
  • Size and portability: Multiline displays are larger and heavier than single-line models. Consider your workspace and whether you need portability.
  • Cost: Multiline displays are significantly more expensive than single-line displays. Evaluate whether the workflow benefit justifies the cost for your situation.
  • Learning curve: Using a multiline display effectively — navigating across lines, understanding the spatial layout — requires some practice beyond what is needed for single-line displays.

Troubleshooting

Display shows nothing / no braille output:

  • Verify the USB or Bluetooth connection and check that the display is powered on.
  • In your screen reader’s braille settings, confirm the correct display model is selected.
  • Try disconnecting and reconnecting. Restart the screen reader if needed.
  • Install or reinstall the vendor’s display driver.

Display shows output but navigation is out of sync:

  • Toggle your screen reader’s braille mode off and on (usually in the braille settings).
  • Restart the screen reader (not the whole computer) and reopen the terminal.
  • Try a different terminal emulator (Windows Terminal, Command Prompt, PowerShell) to see if the issue is terminal-specific.

Display driver not found:

  • Go to the vendor’s website (links below) and download the latest driver for your operating system version.
  • Some displays require firmware updates to work with newer Windows versions.

Routing keys not moving the cursor:

  • In your screen reader’s braille settings, confirm that cursor routing is enabled.
  • In NVDA, this is under Preferences > Settings > Braille > enable “Move system cursor when routing review cursor”.
  • In JAWS, check the routing settings in the JAWS braille configuration.

Vendor Resources

VendorProductsSupport / Drivers
HumanWareBrailliant, BrailleNote Touch+https://www.humanware.com/
Freedom ScientificFocus Blue serieshttps://www.freedomscientific.com/Products/Blindness/FocusBlue/
HIMSBrailleSense, Braille EDGE, Smart Beetlehttps://www.hims-inc.com/
OptelecBraille STAR, Easy Linkhttps://www.optelec.com/
Orbit ResearchGraphiti, Orbit 20/40https://www.orbitresearch.com/
APHMonarchhttps://www.aph.org/
Dot Inc.DotPadhttps://dotincorp.com/
DolphinGuideConnect, braille accessorieshttps://yourdolphin.com/

Connecting a Braille Display: Summary Table

Screen ReaderWhere to Find Braille SettingsRecommended Braille Table for Code
NVDANVDA Menu > Preferences > Settings > BrailleUnified English Braille Grade 1
JAWSInsert+F3 > Options > Basics > Braille (or Settings Center)English Braille Grade 1 (uncontracted)
Windows NarratorSettings > Accessibility > Narrator > BrailleEnglish Grade 1 (uncontracted)
Dolphin SuperNovaCapsLock+SpaceBar > Braille > Display and TranslationGrade 1 (uncontracted)

This page gives a practical overview. Always consult your braille display vendor’s documentation and your screen reader’s braille guide for device-specific setup steps and advanced configuration options.


Part 4: Editor Selection and Accessibility Setup Guide


Table of Contents

  1. Editor Comparison
  2. Editor Setup for 3dMake
  3. Screen Reader Indent Announcement Configuration
  4. Curriculum-Specific Editor Recommendations

Editor Comparison

Overview Table

FeatureNotepadNotepad++Visual Studio Code
CostFree (built-in)FreeFree
Learning CurveMinimalLowModerate
Screen Reader SupportGood (basic)Good (syntax features)Excellent (built-in accessibility)
Extension/Plugin SystemNoneLimitedExtensive
Keyboard NavigationGoodGoodExcellent
CustomizationNoneModerateVery high
PerformanceExcellentVery goodGood
Syntax HighlightingNoneYes (OpenSCAD available)Yes (OpenSCAD available)
Terminal IntegrationNoneNoneBuilt-in
Real-time FeedbackNoneNoneYes (with extensions)
Hot Key CustomizationLimitedGoodExcellent
File Size HandlingGoodGoodExcellent
Built-in DebuggingNoneNoneLimited

Detailed Comparison

Notepad

Advantages:

  • Minimal interface with no distractions-excellent for absolute beginners
  • Very predictable behavior for screen reader users
  • Extremely fast file operations
  • No configuration required; works immediately
  • Pure text editing with no formatting surprises

Disadvantages:

  • No syntax highlighting (OpenSCAD code appears as plain text)
  • No keyboard shortcuts for common editing tasks
  • Limited undo/redo capabilities compared to modern editors
  • No integrated terminal (requires separate command prompt window)
  • No way to run 3dm commands directly

Best For: Users who prefer absolute simplicity and want minimal cognitive load during learning phase

Screen Reader Experience: Windows Narrator reads all content clearly; JAWS and NVDA work well with standard keyboard navigation

Notepad++

Advantages:

  • Lightweight and fast
  • Good syntax highlighting for OpenSCAD code
  • Customizable interface with configurable keyboard shortcuts
  • Tab management for multiple files
  • Better organization than Notepad for managing projects
  • Good screen reader support for basic operations

Disadvantages:

  • No built-in terminal (requires external command prompt)
  • Plugin system is limited compared to VSCode
  • Screen reader experience with syntax highlighting features can be inconsistent
  • Less extensive keyboard customization than VSCode
  • No integrated development environment features

Best For: Users who want a lightweight editor with syntax highlighting but prefer not to use a full IDE

Screen Reader Experience: JAWS and NVDA handle navigation well; Windows Narrator works but may struggle with complex UI elements

Visual Studio Code

Advantages:

  • Extensive built-in accessibility features (accessibility inspector, keyboard navigation shortcuts)
  • Excellent OpenSCAD extension available (scad-preview)
  • Integrated terminal allows running 3dm commands without context switching
  • Powerful keyboard shortcut customization
  • Rich extension ecosystem for workflow enhancement
  • Remote development capabilities
  • Native support for multiple projects and workspaces
  • Excellent search and find/replace functionality

Disadvantages:

  • Steeper learning curve than Notepad or Notepad++
  • Requires initial configuration for accessibility
  • More resource-intensive than lighter editors
  • Built-in terminal can be distracting for some users (alternative: Alt-Tab to standalone terminal)

Best For: Users building comprehensive accessibility workflow and wanting integrated development environment

Screen Reader Experience: Excellent; built specifically with accessibility in mind. NVDA, JAWS, Windows Narrator, and Dolphin all receive high-quality support.

Editor Setup for 3dMake

Setting Default Editor in 3dMake

The 3dMake tool uses your system default text editor. However it can be changed with an edit to the global configuration file by typing this into any terminal.

3dm edit-global-config

You get a file like this in your default text edit program, typically notepad on Windows.

view = "3sil"
model_name = "main"
auto_Start_prints = true
printer_profile = "bambu_labs_X1_carbon"

Add one of the following lines to the end of the file:

editor = "code" for VSCode editor = "notepad" for notepad (already the default) editor = '''C:\Program Files (x86)\Notepad++\notepad++.exe''' for Notepad++ (the triple apostrophes mean you do not have to escape the spaces)

Notepad Setup

Configuration Steps:

  1. Open 3dMake-generated .scad files directly:

    • Navigate to your project folder in File Explorer
    • Right-click the .scad file -> “Open with” -> “Notepad”
    • File opens immediately for editing
  2. Edit and Save:

    • Make changes to your code
    • Press Ctrl+S to save
    • File updates automatically if 3dMake renders in background
  3. Run 3dMake Commands:

    • Save your edits (Ctrl+S)
    • Alt-Tab to Command Prompt or PowerShell window
    • Navigate to project directory: cd C:\path\to\project
    • Run 3dMake command: 3dMake render project.scad

Keyboard Shortcuts:

  • Ctrl+H: Find and Replace
  • Ctrl+G: Go to Line (newer versions)
  • Ctrl+Z: Undo
  • Ctrl+Y: Redo

Notepad++ Setup

Installation and Configuration:

  1. Download from: https://notepad-plus-plus.org/downloads/

  2. Choose: Standard Installer (for automatic system integration)

  3. Configure OpenSCAD Language Support:

    • Open Notepad++
    • Language -> User Defined Language -> Import… (if OpenSCAD UDL available)
    • Or manually set syntax highlighting:
      • Language -> OpenSCAD (if available in language menu)
      • Otherwise Language -> C++ (provides similar highlighting)
  4. Customize for Accessibility:

    • Settings -> Preferences -> General
    • Check: “Minimize to system tray” (optional)
    • Settings -> Preferences -> MISC.
    • Ensure Word Wrap is set to preference
    • Settings -> Preferences -> Backup
    • Enable regular backups of your work
  5. Set as Default Editor (see registry method above)

Recommended Keyboard Shortcuts (User-Defined):

Create custom shortcuts by:

  • Settings -> Shortcut Mapper
  • Add shortcuts for frequently used actions:
    • Save and Switch to Terminal: Alt+T
    • Copy File Path: Ctrl+Shift+C

Tab Management:

  • Open multiple files: Each opens in a separate tab
  • Switch between tabs: Ctrl+Tab (next) / Ctrl+Shift+Tab (previous)
  • Close tab: Ctrl+W

Running 3dMake Commands:

  • Save file with Ctrl+S
  • Alt-Tab to standalone terminal or command prompt
  • Run: 3dMake render filename.scad

Visual Studio Code Setup

Installation:

  1. Download from: https://code.visualstudio.com/ or type winget search VSCode in a terminal and then winget install whichever option you prefer
  2. Install: Run installer and follow prompts
  3. Launch: Open VSCode

Enable OpenSCAD Support:

  1. Open Extensions (Ctrl+Shift+X)
  2. Search: “OpenSCAD”
  3. Install: “scad-preview” by Antyos
  4. Install: “OpenSCAD Syntax Highlighter” (optional, for better syntax highlighting)

Initial Accessibility Configuration:

  1. Open Settings: Ctrl+,

  2. Search: “accessibility”

  3. Enable Key Settings:

    • Accessible View: Toggle ON
    • Screen Reader: Select your screen reader (NVDA, JAWS, Narrator, Dolphin)
    • Keyboard Navigation: Ensure enabled
    • Bracket Pair Guides: Can help with code structure understanding
  4. Configure Editor Font:

    • Search: “editor.fontSize”
    • Set to comfortable size (recommend 14-16 for better readability)
    • Search: “editor.fontFamily”
    • Select monospace font (e.g., “Consolas” or “Courier New”)

Set as Default Editor (see registry method above)

VSCode Terminal Options:

Option 1: Using Built-in Terminal (Less Accessible)

  1. View -> Terminal (or Ctrl+`)
  2. Terminal opens at bottom of VSCode window
  3. Run commands: 3dMake render filename.scad
  4. Note: Switching focus between editor and terminal requires Tab navigation, which can be cumbersome for screen reader users

Keyboard Navigation:

  • Ctrl+` : Toggle terminal visibility
  • Ctrl+Shift+` : Create new terminal
  • Alt+^/v : Switch between terminals
  1. Keep Command Prompt/PowerShell open:

    • Open Command Prompt (Win+R, type “cmd”, Enter)
    • Position window or minimize to taskbar
    • Navigate to project directory: cd C:\path\to\project
  2. From VSCode, switch terminals:

    • Alt+Tab to Command Prompt
    • Run command: 3dMake render filename.scad
    • Alt+Tab back to VSCode
    • Continue editing

Why This Is More Accessible:

  • Screen reader focus switches clearly between two applications
  • Terminal output is read without VSCode context interference
  • Cleaner context switching for command-line workflows
  • Easier to diagnose issues when editor and terminal are separate

Keyboard Shortcuts for Common Tasks:

ActionShortcut
SaveCtrl+S
FindCtrl+F
Find and ReplaceCtrl+H
Go to LineCtrl+G
Open FileCtrl+O
Open FolderCtrl+K, Ctrl+O
Open TerminalCtrl+`
Alt-Tab to Another WindowAlt+Tab
Command PaletteCtrl+Shift+P

Project Organization in VSCode:

  1. Open Project Folder:

    • File -> Open Folder (Ctrl+K, Ctrl+O)
    • Select your project directory
    • All project files appear in Explorer sidebar
  2. File Navigation:

    • Press Ctrl+P for Quick Open
    • Type filename to search and jump to file
    • Press Enter to open
  3. Quick Switch Between Files:

    • Ctrl+Tab : Open recent files list
    • Arrow keys to select
    • Enter to open

Screen Reader Indent Announcement Configuration

Proper indent announcement is critical for OpenSCAD development, as indentation indicates code nesting and structure.

NVDA (NonVisual Desktop Access)

Enable Indent Announcement:

  1. Open NVDA Menu: Alt+N or right-click NVDA icon
  2. Preferences -> Settings (Ctrl+Comma)
  3. Document Formatting: Tab to it
  4. Check: “Report indentation”
  5. In the “Indentation reporting” dropdown: Select “Tones and speech”
  6. Tone Description: NVDA will announce indent level as progressively higher tones (or speaking indent amount)
  7. Apply: Click OK

Additional Tab Stop Configuration:

  1. Preferences -> Settings -> Document Formatting
  2. Check: “Report line indentation”
  3. This will announce: “Indent level 4” or similar as you navigate code

Testing:

  • Open a .scad file with nested code (e.g., difference() { cube(); sphere(); })
  • Press Down Arrow to move line by line
  • NVDA announces indentation level on each new indented line

Keyboard Control:

  • NVDA+3 on Numpad: Cycles indent/outline level reporting

JAWS (Freedom Scientific)

Enable Indent Announcement:

  1. Open JAWS Manager: Press JAWSKey+F2 (or right-click JAWS icon)
  2. Utilities -> Settings Manager
  3. Search: “Indent”
  4. Look for setting: “Announce Indentation” or “Report Indentation”
  5. Enable: Set to “Tones” or “Tones and Speech”
  6. Speech Indent Announcement: Speak indent level
  7. Tone Indent Announcement: Pitch increases with indent level

Advanced Configuration (Custom Scripts):

If built-in settings don’t work:

  1. JAWSKey+F2 -> Utilities -> Settings Manager
  2. Search: “Line Breaks” or “Formatting”
  3. Ensure: “Report line indentation” is enabled
  4. Set tone adjustment: Higher pitch for deeper indents

Testing:

  • Open .scad file with nested code
  • Navigate with arrow keys
  • JAWS announces indent changes with tones or speech

Keyboard Shortcuts:

  • JAWSKey+Alt+I: Toggle indent reporting
  • JAWSKey+Alt+Shift+I: Cycle between indent reporting modes (speech/tones/off)

Windows Narrator

Enable Indent Announcement:

  1. Open Settings: Win+I
  2. Ease of Access -> Narrator
  3. Advanced Options: Scroll down
  4. Check: “Report indentation”
  5. Indentation Reporting: Select “Tones” (less intrusive) or “Speech” (explicit)
  6. Apply settings

Narrator Keyboard Shortcuts:

  • Narrator+Page Down: Read from current position to end of window
  • Narrator+Alt+Arrow Keys: Navigate text
  • Narrator+V, I: Customize indentation reporting (in Narrator settings)

Testing:

  • Open .scad file
  • Use Narrator+Page Down to read through code
  • Listen for indent tone changes or announcements

Note: Windows Narrator has fewer customization options than JAWS/NVDA; consider NVDA or JAWS for deeper indent control

Dolphin EasyConverter (Dolphin Screen Reader)

Enable Indent Announcement:

  1. Open Dolphin Central: Right-click Dolphin icon or click Dolphin icon in taskbar
  2. Utilities -> Settings -> Text Processing
  3. Look for: “Indentation” section
  4. Enable: “Announce indentation”
  5. Mode: Select “Tones”, “Speech”, or “Tones and Speech”
  6. Tone Pitch: Configure pitch increase for deeper indents
  7. Apply

ECO (Ease of Cursor Operation) Customization:

  1. Dolphin Central -> Utilities -> ECO Settings
  2. Text Options -> Indentation Reporting
  3. Set preferred announcement style

Testing:

  • Open .scad file with indented code
  • Navigate with arrows
  • Dolphin announces indent changes

Keyboard Shortcuts:

  • Ctrl+Dolphin+I: Toggle indent reporting on/off
  • Ctrl+Dolphin+Shift+I: Cycle indent reporting mode

Curriculum-Specific Editor Recommendations

For Absolute Beginners (Lesson 1-2)

Recommended: Notepad or Notepad++

Rationale:

  • Minimal interface reduces cognitive load
  • Focus stays on learning OpenSCAD syntax, not editor features
  • Keyboard navigation is straightforward
  • Screen reader experience is predictable

Setup:

  1. Use Notepad or Notepad++ as default editor
  2. Configure screen reader indent announcement
  3. Keep separate Command Prompt window open for 3dMake commands
  4. Alt-Tab workflow between editor and terminal

Workflow Example:

1. Open Command Prompt -> Navigate to project folder
2. Run: 3dMake new myproject
3. Alt+Tab to file explorer, open myproject.scad
4. Notepad++ opens file
5. Edit code
6. Ctrl+S to save
7. Alt+Tab to Command Prompt
8. Run: 3dMake render myproject.scad
9. Check output, return to Notepad++ to refine code

For Intermediate Users (Lesson 3-6)

Recommended: Notepad++ or VSCode

Notepad++:

  • Adds project organization without overwhelming complexity
  • Tab support for managing multiple files
  • Syntax highlighting improves code understanding
  • Still lightweight and predictable

VSCode:

  • Opens doors to more sophisticated workflows
  • Extension system enables advanced features (OpenSCAD preview)
  • Keyboard customization becomes valuable
  • Terminal integration useful but use Alt-Tab method

Setup Decision Tree:

  • Choose Notepad++ if: You prefer simplicity and want to focus on code logic
  • Choose VSCode if: You’re ready to invest time learning editor features for long-term benefit

Workflow Example with VSCode:

1. Open VSCode (folder view of project)
2. Press Ctrl+P to open file search
3. Type filename and press Enter to open
4. Edit code with autocomplete
5. Ctrl+H for find/replace across project
6. Ctrl+S to save
7. Alt+Tab to Command Prompt
8. Run: 3dMake render filename.scad
9. Alt+Tab back to VSCode to refine code

For Advanced Users (Lesson 7-11)

Recommended: Visual Studio Code

Rationale:

  • Powerful search/replace across large projects
  • Extension system enables specialized workflows
  • Keyboard customization reaches full potential
  • Workspace management for complex projects
  • Debugging capabilities aid troubleshooting

Advanced Setup:

  1. Create custom keyboard shortcuts:

    • Ctrl+Alt+R: Save and render current file
    • Ctrl+Alt+P: Preview (if using scad-preview extension)
  2. Install Additional Extensions:

    • “scad-preview”: Real-time 3D preview
    • “Better Comments”: Categorize comments with colors/tones
    • “Bracket Pair Colorizer”: Visual/tonal bracket matching
    • “GitLens”: Track code changes over time
  3. Create Task Runner for Common Commands:

    • Ctrl+Shift+B: Configure build task to run 3dMake
    • Create separate tasks for render, export, etc.
  4. Use Workspaces:

    • File -> Save Workspace As…
    • Save project-specific workspace with all settings
    • Reopen same workspace configuration automatically

Advanced Workflow Example:

1. Open VSCode with project workspace
2. Ctrl+Shift+P -> Run Task -> "3dMake Render Current"
3. Renders file and shows output
4. Use scad-preview extension for real-time 3D view
5. Edit code with advanced search/replace
6. Ctrl+Alt+R saves and renders automatically
7. Use version control (Git) for tracking changes

Quick Reference: Editor Comparison for Curriculum

Foundations (Lessons 1-2)

  • Primary: Notepad or Notepad++
  • Focus: Learn syntax and basic concepts
  • Terminal: Standalone Command Prompt (Alt-Tab)

Core Skills (Lessons 3-6)

  • Primary: Notepad++ or VSCode
  • New Features: Begin using editor syntax highlighting
  • Terminal: Standalone (continue Alt-Tab method)
  • Skills: File organization, search/replace basics

Advanced Projects (Lessons 7-11)

  • Primary: VSCode (strongly recommended)
  • Advanced: Use extensions, real-time preview, complex project management
  • Terminal: Choose Alt-Tab or built-in based on preference
  • Skills: Workspaces, task automation, version control

Troubleshooting Common Issues

Problem: Screen Reader Not Announcing Indent

Solution:

  1. Verify indent announcement is enabled in screen reader settings (see above)
  2. Test with existing .scad file with clear indentation
  3. Try different announcement modes (tones vs. speech)
  4. Restart screen reader: Alt+Ctrl+N (NVDA) or app restart (JAWS)

Problem: 3dMake Commands Not Running from VSCode Terminal

Solution:

  1. Ensure 3dMake is in your system PATH
  2. Use standalone terminal instead (Alt-Tab method) - more reliable
  3. In VSCode terminal, manually navigate to correct directory first
  4. Verify command syntax: 3dMake render filename.scad

Problem: File Not Saving in Editor

Solution:

  1. Verify you pressed Ctrl+S
  2. Check file permissions on project folder
  3. Try “Save As” instead
  4. Ensure filename includes .scad extension

Problem: Syntax Highlighting Not Working

Solution:

  1. Verify file has .scad extension
  2. In Notepad++: Language menu -> select OpenSCAD or C++
  3. In VSCode: Install OpenSCAD extension (search Extensions)
  4. Restart editor

Problem: Alt-Tab Not Switching Between Windows

Solution:

  1. Ensure Command Prompt is open and minimized (not closed)
  2. Press Alt+Tab and hold briefly to see window switcher
  3. Use Alt+Tab multiple times if more than 2 windows open
  4. Alternatively, click taskbar directly (Alt+Tab usually more accessible)

Next Steps

After completing this setup guide:

  1. Choose your editor based on the recommendations for your skill level
  2. Configure screen reader indent announcement immediately (critical for code structure understanding)
  3. Set editor as default for .scad files
  4. Test with a simple file: Create a test project and edit it
  5. Practice Alt-Tab workflow before moving to Lesson 1
  6. Document your setup in a personal note for reference

You are now ready to begin Lesson 1: Environmental Configuration and Developer Workflow

Additional Resources

Safety Protocols and the Physical Fabrication Interface

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

Every lesson so far has been entirely digital: code on a screen, commands in a terminal, virtual geometry. Now we’re moving into the physical world. 3D printers are machines that get very hot, draw substantial electrical current, and produce airborne particles and vapors. This lesson exists because these machines are genuinely safe when you know what you’re doing, and genuinely dangerous when you don’t.

The good news is that 3D printing safety is not complicated. The hazards are well-understood, the mitigations are straightforward, and the incidents that do happen are almost always caused by ignoring simple rules. The goal of this lesson is to make sure you know the rules and understand why they exist — not just as things to memorize for a quiz, but as habits you can apply in any shop or makerspace you ever work in.


Learning Objectives

By the end of this lesson you will be able to:

  • Identify and apply the Hierarchy of Controls for 3D printing hazards
  • Apply fire, electrical, and fume safety protocols for FDM printing
  • Understand filament-specific hazards and safe material handling
  • Follow a safe printer startup, monitoring, and shutdown sequence
  • Select appropriate filament materials for given projects
  • Use pre-flight build scripts to estimate cost before committing to a print
  • Design parts that minimize safety risks during printing

Concept 1: The Hierarchy of Controls

Why We Don’t Just “Be Careful”

When it comes to workplace and lab safety, the common advice “just be careful” is the least effective approach available. It relies entirely on individual attention, and attention is inconsistent — everyone gets tired, distracted, or hurried sometimes. Professional safety systems are designed to work even when individual attention lapses.

The Hierarchy of Controls is a framework developed by OSHA (the U.S. Occupational Safety and Health Administration) and adopted worldwide. It ranks safety strategies from most effective to least effective, and it says: apply the most effective strategy you can afford, and layer additional strategies below it.

The five levels, from most to least effective:

1. Elimination — Remove the hazard entirely. If a filament requires a sealed enclosure with active filtration and you’re in an open classroom, the safest choice is simply not to use that filament. If a print requires supports made from difficult material, redesign the print to not need supports. Elimination always wins.

2. Substitution — Replace the hazard with a less dangerous one. Use PLA instead of ABS. Use a PEI spring steel bed instead of a glass bed that can shatter. Substitution keeps the functionality while reducing the risk.

3. Engineering Controls — Build protection into the environment. A fume enclosure with a HEPA + activated carbon filter. Thermal runaway protection in the printer firmware. A smoke detector mounted above the printer. These controls work automatically without relying on human behavior.

4. Administrative Controls — Rules, procedures, and training. The startup checklist, the monitoring schedule, the training program you’re in right now. Administrative controls are less reliable than engineering ones because they depend on people following rules consistently.

5. Personal Protective Equipment (PPE) — Gloves, goggles, respirators. PPE is the last resort — it protects one person, it can fail or be used incorrectly, and it doesn’t actually remove the hazard. Always apply higher-level controls first and use PPE as a supplement.

The key insight: many beginners think that putting on gloves and goggles makes them safe. In the hierarchy, PPE is the weakest protection. Real safety comes from eliminating or substituting hazards, and then engineering the remaining risks away. PPE is what you use when those options aren’t available.


Step 1 — Fire and Electrical Safety

The Golden Rule

Never leave an FDM printer completely unattended during the first layer. Print failures most often happen at the start — the first layer either bonds to the bed or it doesn’t. If it doesn’t bond and nobody is watching, the printer may continue for hours, dragging filament across the bed in a mess called “spaghetti” that can tangle around the print head, cause jams, or — in rare worst cases — create a fire hazard.

Be present and watching for at least the first 15 minutes of every print. For long prints, check in every 30 minutes or set up remote monitoring via OctoPrint or a camera.

Fire Hazards

Fire risk in FDM printing comes from two main sources. First, electrical failure: wiring that cracks from repeated movement, loose connections at terminal blocks, or a faulty temperature sensor that allows the heater to run without limit. Second, filament accumulation: plastic that melts and collects on the hot nozzle can sometimes ignite if the build-up becomes large enough.

Fire safety protocols:

  • Keep a Class ABC fire extinguisher within arm’s reach of every printer
  • Never run the printer while away from the building
  • Keep the print area clear of flammable materials: paper, fabric, solvent containers
  • Mount a smoke detector directly above the printer so rising smoke reaches it quickly
  • Know where the power switch is before you start — cutting power is the first response to any emergency
  • If smoke appears: cut power immediately, do not try to continue the print, and report the incident

Electrical Safety

  • Use a surge protector to protect the printer’s control board from voltage spikes
  • Inspect all wiring periodically, especially the flexible cable bundle that runs to the heated bed — this bundle flexes with every print and can crack the insulation over time
  • Thermal runaway protection must be enabled. This firmware feature monitors the temperature sensor and shuts the heater off if the temperature climbs unexpectedly or the sensor fails. A printer without thermal runaway protection can overheat catastrophically. Never disable this protection. If your printer doesn’t have it, do not use it.
  • Never open the power supply enclosure or work on any electrical component while the printer is plugged in. The power supply contains mains voltage (120V or 240V) that can kill.

Step 2 — Fume Safety

Why Fumes Matter

All FDM printing produces some airborne emissions. These fall into two categories: particulates (tiny plastic particles, especially ultrafine particles below 0.1 microns) and VOCs (volatile organic compounds — chemical vapors that off-gas from the hot plastic). Both can affect respiratory health with repeated exposure, and the risk varies significantly by material.

MaterialFume RiskRequired Mitigation
PLALowGood room ventilation (open window or HVAC on)
PETGLow–MediumActive ventilation; avoid enclosed spaces without air exchange
ABSHighDedicated fume enclosure with HEPA + activated carbon filter required; NOT safe for open classrooms
ASAHighSame as ABS
TPUMediumActive ventilation; keep nozzle temperature at the minimum needed
Resin (SLA/MSLA)Very HighFull enclosure; nitrile gloves; UV-blocking goggles; no open-workspace use

The Safe Choice: PLA

PLA (Polylactic Acid) is the safest classroom filament available. It is made from bio-derived sources (corn starch or sugarcane), prints at relatively low temperatures (190–220°C), produces the lowest emissions of any common FDM material, and is forgiving of settings variations. For any classroom project where the mechanical requirements don’t specifically demand a different material, default to PLA.

What “Good Ventilation” Actually Means

“Good ventilation” means that the air in the room is actively exchanging with outside air. This is not the same as “a window that’s crackable.” Active ventilation means:

  • A window open with a fan pulling air through the room, or
  • An HVAC system that is running and moving air, not just recirculating internal air

If you’re printing ABS or ASA, room ventilation is not sufficient. You need an enclosure with a filtered exhaust system — a box around the printer with an internal fan that pulls fumes through a HEPA filter (for particles) and an activated carbon filter (for VOCs) before exhausting outside or into a large ventilated space.


Step 3 — Material Selection

Choosing the Right Filament

The right material for a project depends on what the part needs to do and where it will be used. This table gives you a practical guide:

FilamentStrengthFlexibilityHeat ResistancePrint DifficultyBest Uses
PLAMediumRigidLow (softens at 50–60°C)EasyPrototypes, display models, artwork, educational parts
PETGMedium-HighSlightly flexibleMedium (75–80°C)Easy–MediumFunctional parts, food-adjacent applications, water contact
ABSHighSemi-rigidHigh (85–100°C)HardHot environments, automotive interiors, post-processing (acetone smoothing)
TPUMediumVery flexibleMediumMediumGaskets, grips, phone cases, flexible joints
NylonVery HighFlexibleHighHardMechanical parts, gears, load-bearing functional parts
ASAHighSemi-rigidVery High (90°C+)HardOutdoor use, UV-exposed parts

What “Hard” to Print Actually Means

When a material is listed as “hard,” that means it requires one or more of the following: a higher nozzle temperature, a heated enclosure to prevent warping, special bed adhesion (glue stick, hairspray, specialized plates), slower print speeds, or more careful tuning of retraction settings. Starting with a difficult material before you have PLA dialed in is a recipe for frustration and wasted filament.

The practical rule: use PLA until you have a specific reason not to. When you need better heat resistance, try PETG next. ABS and specialty materials come later, with appropriate safety infrastructure.

PLA and Sustainability — A Realistic Picture

PLA is often marketed as “biodegradable” and “eco-friendly.” These claims deserve some scrutiny. PLA is bio-derived — made from fermented plant starch rather than petroleum — which reduces its carbon footprint somewhat compared to petroleum plastics. But PLA only biodegrades under very specific industrial composting conditions (temperatures above 58°C sustained for weeks). It does not break down in a home compost bin or a landfill.

The most sustainable approach to FDM printing is not any particular material — it’s designing durable parts that don’t need to be reprinted, using the minimum infill that meets your mechanical requirements, and avoiding test prints you don’t need (which is exactly why this course emphasizes verification before printing).


Step 4 — Estimating Print Cost Before You Print

Always Estimate First

Sending a model to print without checking the cost is like placing a restaurant order without looking at the price. For short prints of small parts, the filament cost is trivial (often under $0.50). But for large, high-infill parts, it can be several dollars — and more importantly, it represents several hours of printer time that you can’t get back if the part turns out to need revision.

The estimate formula from Lesson 1 applies here:

mass (grams)  = (volume_mm³ ÷ 1000) × filament_density_g_per_cm³
cost ($)      = mass × (spool_price_$ ÷ spool_weight_g)

The preflight scripts below automate this calculation and require you to confirm before proceeding.

Pre-Flight Cost Check Scripts

Linux / macOS (bash):

#!/bin/bash
set -e

3dm build
INFO=$(3dm info)
echo "$INFO"

# Extract volume from 3dm info output
VOLUME=$(echo "$INFO" | grep -oP '(?<=Volume:\s)\d+\.?\d*')
if [ -z "$VOLUME" ]; then
  echo "ERROR: Could not parse volume from 3dm info output"
  exit 1
fi

DENSITY=1.24    # g/cm³ — PLA density (change for other materials)
COST_PER_G=0.02 # $/g  — adjust for your spool price

MASS=$(echo "$VOLUME $DENSITY" | awk '{printf "%.1f", ($1/1000)*$2}')
COST=$(echo "$MASS $COST_PER_G" | awk '{printf "%.2f", $1*$2}')

echo ""
echo "=== PRE-FLIGHT SUMMARY ==="
echo "Volume:   ${VOLUME} mm³"
echo "Mass:     ${MASS} g  (PLA @ ${DENSITY} g/cm³)"
echo "Filament: \$${COST}  (@ \$${COST_PER_G}/g)"
echo ""
echo "Proceed? [y/N]"
read CONFIRM
if [ "$CONFIRM" != "y" ]; then
  echo "Cancelled."
  exit 0
fi
echo "Approved. Send to slicer."

Windows (PowerShell):

3dm build
$info = 3dm info
Write-Host $info

$volumeMatch = $info | Select-String -Pattern "Volume:\s+([\d.]+)"
if (-not $volumeMatch) { Write-Error "Could not parse volume"; exit 1 }
$volume = [double]$volumeMatch.Matches.Groups[1].Value

$density  = 1.24    # PLA
$costPerG = 0.02
$mass     = ($volume / 1000) * $density
$cost     = $mass * $costPerG

Write-Host ""
Write-Host "=== PRE-FLIGHT SUMMARY ==="
Write-Host ("Volume:   {0:F0} mm3" -f $volume)
Write-Host ("Mass:     {0:F1} g  (PLA)" -f $mass)
Write-Host ("`$Filament: {0:F2}" -f $cost)
Write-Host ""
$confirm = Read-Host "Proceed? [y/N]"
if ($confirm -ne "y") { Write-Host "Cancelled."; exit 0 }
Write-Host "Approved. Send to slicer."

Step 5 — The Printer Startup Checklist

Before Every Print Session

Use this checklist before starting any print. It takes about 5 minutes and prevents the most common causes of print failure.

PRINTER STARTUP CHECKLIST
□ Bed level verified (run auto-level, or manually check at all four corners)
□ Build plate clean (wipe with IPA — remove finger oils and dust)
□ Nozzle cleared (cold pull if returning from more than a day idle)
□ Filament loaded and extruding cleanly (run 50mm manual extrude purge)
□ First layer height set correctly (0.2mm gap typical for 0.4mm nozzle)
□ Print fan operational (watch it spin up at the start)
□ Workspace clear of flammable materials
□ You will remain present for the first 15 minutes of the print
□ Power switch is accessible and you know where it is

Why Each Item Matters

Bed leveling is the single most critical setting for successful prints. The first layer needs to be squished gently against the bed — close enough to bond, but not so close that filament can’t flow. A bed that’s 0.1 mm too high or too low can cause every print to fail. Most modern printers have automatic bed leveling (ABL), but you should still understand how it works and check that it’s running correctly.

Clean build plate prevents adhesion failures. Skin oils from touching the plate are invisible but dramatically reduce how well plastic sticks. An isopropyl alcohol (IPA) wipe before every print takes 30 seconds and prevents a common failure mode.

Cold pull (nozzle clearing) removes degraded filament from inside the nozzle. Heat the nozzle to print temperature, push some filament through, then let it cool to about 90°C and pull the filament out firmly. The end of the pulled filament should bring out any debris or degraded material from inside the hot end.

Filament loaded correctly means the extruder is feeding without clicking or skipping, the filament is straight in the Bowden tube (if present), and the purge line at the start of the print flows smoothly with no bubbles or gaps.


Step 6 — Monitoring During Prints

What to Watch For

Checking in periodically during a print takes only a few seconds each time and lets you catch problems early. A problem caught at layer 10 is a minor inconvenience. The same problem discovered at layer 100 means you’ve wasted 90 layers of material and print time.

Spaghetti — when the part lifts off the bed and the nozzle starts dragging filament through the air instead of depositing it in layers. The result looks like a pile of plastic spaghetti. This is the most common failure mode and the most important to catch early. If you see it, pause or cancel the print immediately.

Layer shifts — a horizontal displacement somewhere in the print, where part of the model is offset from the rest. This usually indicates a mechanical problem (belt tension, loose pulley, or a motor missing steps). Cancel the print and diagnose the cause before trying again.

Nozzle clog — the extruder starts making a clicking or ticking sound as the gear slips because material isn’t flowing. Filament may start grinding. Pause the print and clear the clog before restarting.

Stringing — thin wisps of filament connecting different parts of the print. Usually a retraction or temperature setting issue rather than an emergency, but it may require post-processing cleanup.

Smoke — immediate emergency. Cut power. Do not attempt to continue or diagnose while the printer is running. Notify your instructor. Do not restart the printer until the cause has been fully identified and corrected.


Step 7 — Safe Shutdown and Part Removal

The Right Way to End a Print

A print ending doesn’t mean the work is done. Follow these steps after every print:

  1. Wait for the nozzle to cool below 50°C before reaching anywhere near the hot end. The nozzle can reach 200°C+ during printing and retains heat for several minutes after shutdown.

  2. Wait for the bed to cool below 30°C before removing the part. Parts printed on a hot bed can warp slightly if removed while the bed is still warm. Many PEI-coated beds release parts naturally as they cool — you may not even need tools.

  3. Use a spatula or palette knife to gently separate the part from the build plate. Never force parts off with your fingers — the edge of a part against a spring steel bed can cut skin. Apply the spatula at a low angle and use a gentle rocking motion.

  4. Store filament in a sealed bag with desiccant. Filament absorbs moisture from the air (this is called hygroscopy), and moisture in filament causes bubbling, popping, and reduced mechanical properties during extrusion. This is especially important for Nylon and PETG. A small silica gel desiccant packet inside a ziplock bag is sufficient for short-term storage.


Concept 2: Design for Printability and Safety

Your Design Choices Affect Safety

The decisions you make in OpenSCAD directly affect how safe and reliable the printing process will be. Good design doesn’t just mean a part that looks right — it means a part that prints reliably without requiring dangerous materials, excessive supports, or heroic printer tuning.

Minimize overhangs. Any geometry that extends more than about 45° from vertical needs supports — temporary scaffolding that the printer adds automatically. Supports increase print time, use more material, often leave rough marks where they’re removed, and increase the risk of print failure due to tangled support material. Good design reorients parts or modifies geometry to eliminate or reduce overhangs.

Maintain minimum wall thickness. For a 0.4 mm nozzle, walls below 0.8 mm (two nozzle widths) may not print reliably. Walls below 1.2 mm (three nozzle widths) are marginal for any kind of structural use. Walls below about 0.8 mm may not appear in the sliced output at all — the slicer simply omits them as too small.

Use the safest material that meets requirements. If PLA is strong enough, use PLA. Don’t introduce PETG, ABS, or specialty materials unless you have a specific reason and the appropriate safety infrastructure.

Encode printability constraints in your code:

// Printability constants — these drive safe design decisions
wall_min     = 1.2;    // mm — minimum wall for 0.4mm nozzle (3× nozzle width)
hole_min_r   = 1.5;    // mm — minimum hole radius for reliable circular holes
clearance    = 0.2;    // mm — fitting clearance between mating faces
overhang_max = 45;     // degrees — maximum overhang without supports

module printable_box(w, d, h, wall=2) {
  // Validate against printability limits
  assert(wall >= wall_min, str("wall (", wall, "mm) must be >= ", wall_min, "mm"));
  assert(w > 2 * wall, "width must be greater than two wall thicknesses");
  assert(d > 2 * wall, "depth must be greater than two wall thicknesses");

  // Open-top box: no overhangs on the inside
  difference() {
    cube([w, d, h]);
    translate([wall, wall, wall])
      cube([w - 2*wall, d - 2*wall, h]);  // open at top — no overhang required
  }
}

printable_box(50, 40, 30);

Exercises

Exercise 5.1: Run 3dm info on your model from Lesson 3. Calculate the material cost in PLA and in PETG (density 1.27 g/cm³). If PLA spools cost $20/kg and PETG spools cost $25/kg, what is the cost difference for your part?

Exercise 5.2: Write a pre-flight script (bash or PowerShell) that builds your model, reports the estimated cost, and requires a y confirmation before proceeding.

Exercise 5.3 (Advanced): Modify the pre-flight script to accept a --material argument (options: pla, petg, abs, tpu) and calculate cost using the correct density for the selected material.


Quiz — Lesson 5 (15 questions)

  1. What are the five levels of the Hierarchy of Controls, from most to least effective?
  2. Why is Elimination considered the most effective safety control?
  3. Which filament requires a dedicated fume enclosure with HEPA + activated carbon filtration and is NOT recommended for open classrooms?
  4. At what temperature should you wait before removing a print from the bed?
  5. What should you do immediately if you see smoke coming from your 3D printer?
  6. Give three reasons why PLA is considered the safest classroom filament.
  7. What is the minimum reliable wall thickness for a 0.4 mm nozzle, and why does this minimum exist?
  8. What is the purpose of storing filament with desiccant?
  9. True or False: It is safe to leave a 3D printer completely unattended for hours once the first layer has printed successfully.
  10. What is “spaghetti” in the context of a 3D printing failure, and what causes it?
  11. What is thermal runaway protection, and why is it critical that it remain enabled?
  12. What are the two types of airborne emissions from FDM printing, and which filaments produce the most hazardous levels of each?
  13. Describe one engineering control and one administrative control you could implement in a classroom 3D printing lab.
  14. Explain why minimizing overhangs in your design is both a safety consideration and a quality consideration.
  15. A student wants to print a car dashboard mount in ABS because it will be in a hot car. The classroom has no fume enclosure. Using the Hierarchy of Controls, what recommendations would you make?

Extension Problems (15)

  1. Create a material selection flowchart that guides a user from mechanical requirements to the safest filament that meets them.
  2. Conduct a ventilation assessment of your classroom or makerspace. Document air exchange methods, window locations, and any existing filtration.
  3. Write a Standard Operating Procedure (SOP) for ABS printing that includes all required safety equipment and ventilation infrastructure.
  4. Design and describe a “first layer test tile” — a 100 × 100 × 0.4 mm flat tile — and explain how you’d use it to verify bed leveling.
  5. Build a parametric filament storage clip in OpenSCAD: a clip that holds the free end of a filament spool. Parameters: filament diameter, clip width.
  6. Research OSHA’s published guidance on VOC exposure in 3D printing environments. Summarize the key recommendations.
  7. Compare the Safety Data Sheets (SDS) for PLA and ABS filament from two manufacturers. Document differences in recommended exposure limits and PPE.
  8. Design a simple printer enclosure in OpenSCAD: four walls, a front door opening, and a top panel with a circular vent hole. Document the parametric variables.
  9. Create a safety poster covering the five most important 3D printing safety rules, organized using the Hierarchy of Controls framework.
  10. Write a one-page risk assessment for a new FDM printer being added to a classroom.
  11. Design and describe a parametric filament moisture indicator holder: a small box that holds a humidity indicator card inside a resealable filament storage bag.
  12. Build a “print monitoring log” template: a paper form with columns for time, nozzle temperature, bed temperature, layer number, visual observations, and action taken.
  13. Research the difference between particle emissions and VOC emissions from FDM printing. Which is considered more hazardous at typical classroom distances from the printer?
  14. Design a parametric build plate corner protector: a small clip that attaches to the edge of a glass or spring steel build plate to protect it from spatula damage.
  15. Write a hypothetical “near-miss incident report” for a fictional 3D printing incident using a standard workplace incident report format (date, location, description, contributing factors, corrective actions).

References and Helpful Resources

  • OSHA Hierarchy of Controls — https://www.osha.gov/hierarchy-of-controls / NIOSH — https://www.cdc.gov/niosh/topics/hierarchy/default.html
  • UL Research Institutes — 3D Printing Emissions Study — https://www.ul.com/news/ul-research-institutes-releases-3d-printing-emissions-study
  • NIOSH Science Blog — Health and Safety Considerations for 3D Printing — https://blogs.cdc.gov/niosh-science-blog/2020/05/14/3d-printing/
  • PrusaSlicer Documentation — https://docs.prusa3d.com/en/
  • All3DP Filament Types — https://all3dp.com/1/3d-printer-filament-types-3d-printing-3d-filament/
  • MatterHackers Filament Compare — https://www.matterhackers.com/3d-printer-filament-compare
  • Prusa Research Materials Guide — https://help.prusa3d.com/materials

Supplemental Resources

  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake
  • OpenSCAD User Manual — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Reference Appendices

All supporting documents for Lesson 5 are included below. You do not need to open any additional files.


Appendix A: Safety Checklist for 3D Printing

Complete this checklist before and after each printing session. Print it out and keep a copy at your printer station.


Pre-Print Setup

Work Area

  • Desk or table cleared of unnecessary items
  • Tripping hazards removed from around the printer
  • Adequate ventilation confirmed (window open, fan running, or fume enclosure active)
  • Class ABC fire extinguisher within arm’s reach
  • Smoke detector mounted above printer is functional

Printer Inspection

  • Nozzle is clean — no old filament residue baked on
  • Build plate is level (re-level if the printer has been moved or bumped)
  • Heated bed temperature sensor is attached and secure
  • All cables are secure and none are frayed or cracked — especially the flexible bed cable bundle
  • Thermal runaway protection is enabled (check firmware settings if unsure)

Filament Preparation

  • Filament spool rotates freely on the holder — no binding or tangling
  • Filament path is clear of obstructions from spool to extruder
  • Extruder drive gear is clean — not clogged with ground plastic
  • Filament is correctly loaded and primed (a few mm of filament extruded before starting)

Environmental Conditions

  • Room temperature is adequate (18–25°C ideal — extreme cold slows bed heating; extreme heat can soften PLA)
  • No direct drafts from windows or air conditioning blowing on the printer (drafts cause warping and layer splitting)
  • Adequate lighting to clearly see the first layer as it prints

During Print

First Layer Monitoring (Do Not Leave)

  • Watch the first 2–3 layers without interruption
  • Bed adhesion is correct — filament sticks flat, not lifting at corners or curling
  • Nozzle temperature is stable at target value
  • No unusual sounds (grinding, clicking, popping)

Regular Checks (Every 15–30 Minutes)

  • Print is building correctly — no layer shifting, no spaghetti
  • Filament is feeding smoothly from the spool
  • No grinding or skipping sounds from the extruder
  • No warping visible at part edges

Temperature Stability

  • Heated bed maintains consistent temperature throughout
  • Nozzle temperature does not fluctuate more than ±5°C
  • No thermal runaway warnings on the printer display

Stop the Print Immediately If

  • The nozzle jams or extrudes unevenly
  • Filament stops feeding entirely
  • Any burning smell is detected
  • Visible layer shifting occurs
  • Grinding or skipping sounds from the extruder
  • Any unusual chemical or burning odor
  • Smoke appears — cut power immediately

Post-Print

Cool Down

  • Allow the heated bed to cool naturally for 10–15 minutes before attempting print removal
  • Keep hands clear of the nozzle until it reads below 50°C
  • Confirm the printer is idle and all temperatures are dropping before touching

Print Removal

  • Use a proper spatula or scraper — not fingers or improvised tools
  • Remove the print only when the bed has fully cooled (PLA releases easily from PEI beds when cool)
  • Inspect the print for sharp edges, support stubs, or layer delamination
  • Sand or file sharp edges if the part will be handled

Equipment Cleaning

  • Wipe the nozzle with a brass wire brush when cooled to 50°C (never cold — residue must be slightly soft)
  • Remove any plastic debris and failed print material from the build plate
  • Check the extruder for embedded filament residue
  • Clear any visible dust from the electronics area

Workspace Cleanup

  • Return all tools to their proper storage location
  • Dispose of support material and failed prints in a bin (not on the floor)
  • Store filament in a sealed bag with desiccant
  • Confirm the workspace is clear and safe for the next user

Hazard Reference Summary

HazardTemperature / ConditionResponse
Hot nozzle190–260°CDo not touch; wait for < 50°C
Hot bed50–110°CDo not touch; allow full cool-down
Fumes (ABS/PETG)At operating tempVentilate; use enclosure with filtration
Electrical (power supply)120V / 240V mainsNever open while plugged in
Tangled filamentAnyClear before printing; never force-pull

Emergency Actions

  • Fire: Unplug immediately. Use a dry chemical (Class ABC) extinguisher — NOT water on electrical fires. Evacuate and call emergency services.
  • Burns: Rinse with cool (not cold) running water for 15+ minutes. Seek medical attention for any burn larger than a coin.
  • Fume inhalation: Move to fresh air immediately. Seek medical attention if symptoms (headache, dizziness, nausea) persist.

Last Reviewed: __________ Reviewed By: __________


Appendix B: Filament Comparison Table

Quick reference for choosing the right filament. All temperature values are typical ranges — always check the label on your specific spool. The spool always wins over this table.


Side-by-Side Comparison

PropertyPLAPETGTPU (Flex)ABS
DifficultyEasiestModerateHardVery Hard
Nozzle temp190–220°C230–250°C220–240°C230–250°C
Bed temp50–60°C70–85°C30–60°C90–110°C
Enclosure needed?NoNoNoYes
RigidityHighMediumNone — flexibleHigh
Impact resistanceLow (brittle)MediumVery highMedium
Heat resistanceLow (~60°C)Medium (~80°C)MediumHigh (~100°C)
FlexibilityNoneSlightRubber-likeNone
Moisture sensitivityLowMediumHighMedium
Fume concernLowestLowModerateHigh
Bed adhesionEasyUse glue stick on PEIEasyRequires enclosure + glue
Print speedNormalNormalSlow (20–30 mm/s)Normal
Stringing tendencyLowMedium–HighHighLow
Approximate cost$15–25/kg$15–30/kg$20–40/kg$15–25/kg
Recommended for beginners?✅ YesAfter PLAAfter experience❌ No

When to Use Each Material

PLA — Use for:

  • Prototypes and test prints
  • Classroom projects
  • Decorative objects and tactile models
  • Anything that won’t be exposed to heat, moisture, or heavy mechanical stress

PLA — Avoid for:

  • Objects left in a hot car or direct sun (softens above ~60°C)
  • Parts that need to flex or bend without cracking
  • High-impact applications

PETG — Use for:

  • Functional parts that need to be tougher than PLA
  • Parts exposed to mild heat or moisture
  • Mechanical components: brackets, clips, mounts
  • Food-contact applications (check your specific brand for food-safe certification)

PETG — Avoid for:

  • Very fine surface detail (it strings more than PLA)
  • Projects where you need the easiest possible first-time print

TPU / Flexible — Use for:

  • Wearable objects (wristbands, phone cases, watch straps)
  • Bumpers and shock absorbers
  • Grips and handles
  • Objects that must deform under pressure and return to shape

TPU — Avoid for:

  • Fine surface detail
  • Printers with Bowden extruders (the flexible filament buckles in the tube — direct drive only)
  • Your first few prints while still learning

ABS — Use for:

  • High-heat environments (car interiors, near motors)
  • Parts requiring post-processing (ABS sands, bonds with acetone vapor, and paints easily)
  • Professional or industrial contexts with proper dedicated ventilation

ABS — Avoid for:

  • Any classroom without a dedicated sealed fume enclosure and active filtration
  • Beginners
  • Any print where warping at the edges would be a problem and you have no enclosure

Slicer Profile Quick Reference

FilamentPrusaSlicer ProfileKey Changes from PLA Default
PLAGeneric PLABaseline — no changes needed
PETGGeneric PETGHigher temps; slower cooling; glue stick on PEI bed
TPUGeneric FlexReduce speed to 20–30 mm/s; reduce retraction
ABSGeneric ABSHigher temps; disable cooling fan; use enclosure

Filament Storage

All filament absorbs moisture from the air over time. Wet filament causes: popping or crackling sounds during printing, bubbles in extruded plastic, excessive stringing, and weak or brittle finished parts.

FilamentMoisture SensitivityStorage Recommendation
PLALowSealed bag with desiccant when not in use
PETGMediumSealed bag with desiccant; dry before use if stored open for weeks
TPUHighAlways store sealed; dry in oven at 65°C for 4–6 hours if moisture-absorbed
ABSMediumSealed bag with desiccant

Sources: All3DP Filament Types Guide; MatterHackers Filament Compare; Prusa Research Materials Guide


Appendix C: Material Properties Quick Reference

Essential material data for FDM/FFF printing. Use alongside the Filament Comparison Table for material selection decisions.


Properties at a Glance

PropertyPLAPETGABSTPU
Nozzle temp (°C)200–220235–250240–260220–240
Bed temp (°C)20–6070–90100–11020–60
StrengthModerateHighVery HighLow (flexible)
FlexibilityNoneSlightSlightHigh
Ease of printingVery EasyEasyHardModerate
Cost ($/kg)$15–25$20–30$18–28$30–50
Print speed40–60 mm/s30–50 mm/s20–40 mm/s10–30 mm/s
Bed adhesionEasyModerateRequires prepEasy
UV resistanceLowModerateHighLow
Chemical resistanceNoModerateYesNo

Heat Resistance After Printing

This is one of the most common reasons to choose a material other than PLA.

MaterialSafe to use up toSoftens atNotes
PLA~50–60°C~60–70°CNot suitable for car interiors or items near heat sources
PETG~80–100°C~100–110°CHandles warm environments well
ABS~90–110°C~110–120°CGood heat resistance; most demanding to print
TPU~60–80°C~80–100°CLimited heat resistance despite flex durability

Chemical Resistance

MaterialWaterAlcoholAcetoneOilsAcids
PLALowLowDissolvesLowLow
PETGHighModerateModerateHighModerate
ABSHighModerateDissolvesHighModerate
TPUModerateLowLowModerateLow

Acetone note: Can be used to smooth ABS surfaces (vapor or liquid application). Also dissolves PLA — keep acetone away from PLA prints and filament spools.


Strength After Printing — Curing Time

Freshly printed parts are not at full strength.

Time After PrintingApproximate Strength
0–24 hours70–80% of final strength
24–48 hours90–95% of final strength
48–72 hours~99% of final strength
7+ daysMaximum strength

Do not stress-test functional parts immediately after printing. Allow at least 24 hours before load testing.


Storage Conditions

FactorRecommended Range
Storage temperature15–25°C
Relative humidity30–50%
Light exposureAway from direct sunlight
ContainerSealed with desiccant packets

Quick Material Selection Guide

QuestionAnswer
First time printing?PLA
Need durability?PETG or ABS
Need flexibility?TPU
Need high strength?ABS or PETG
Quick test / prototype?PLA
Outdoor use?PETG or ABS
Food contact?Food-grade certified PETG (verify brand)
Heat resistant?ABS
Easiest possible print?PLA

Appendix D: Printer Maintenance Log

Copy this log and keep a printed or digital copy with your printer. Fill in the Printer Information section first, then log every maintenance event and issue as it occurs. A complete log is your best diagnostic tool when problems arise.


Printer Information

FieldValue
Printer model
Serial number
Purchase date
Firmware version
Last service date
Warranty expiry
Manufacturer support contact

Maintenance Schedule

Before each use (Daily)

  • Visual inspection — no visible damage, cables intact
  • Clean nozzle tip if residue is present
  • Verify build plate is level (re-level if printer was moved)
  • Confirm filament spool rotates freely with no tangles

Weekly

  • Clean extruder drive gear (compressed air or brush out ground plastic)
  • Inspect and wipe Z-axis rails and lead screw
  • Check all cable connections at the control board
  • Test emergency stop / power cut

Monthly

  • Full build plate leveling procedure (manual or automatic)
  • Clean interior of print chamber
  • Inspect heating elements and thermistor connections
  • Run a temperature calibration test print

Quarterly (every 3 months)

  • Replace nozzle if inner bore shows wear or repeat clogging
  • Full mechanical inspection — belt tension, eccentric nuts, frame screws
  • Check firmware for updates
  • Run a full calibration test print and document results

Maintenance Log

DateTypeDescriptionTime SpentIssues FoundResolutionBy

Types: Routine / Repair / Calibration / Cleaning / Part replacement


Issue Tracking Log

DateSymptomDiagnosisAction TakenStatusNotes

Statuses: Open / In progress / Resolved / Monitoring


Parts Replacement Record

DatePart ReplacedReasonSupplierCostNotes

Filament Compatibility Notes

Record your tested settings for each material on this specific printer. Published temperature ranges are starting points — your printer may run hotter or cooler than its display indicates.

FilamentBrandNozzle TempBed TempSpeedSuccess RateNotes
PLA
PETG
ABS
TPU
Other

Troubleshooting Quick Reference

Nozzle Clog

  • First response: Cold pull (heat to printing temp, push filament through manually, cool to 90°C, pull sharply)
  • Second response: Acupuncture needle or nozzle cleaning filament
  • Last resort: Replace nozzle

Bed Adhesion Problems

  • Check: Bed level, nozzle height from bed, bed surface condition (clean? worn?)
  • Fix by material: PLA → clean PEI with IPA; PETG → apply glue stick; ABS → glue stick + enclosure

Layer Shifting

  • Common causes: Belt too loose, motor current too low, print speed too high, X/Y axis obstruction
  • Check belt tension first — it’s the most common cause

Extrusion Issues (Under-extrusion)

  • Common causes: Partial clog, worn drive gear, incorrect extruder steps/mm, wet filament
  • Run a flow rate test: extrude 100 mm and measure actual output

Monthly Performance Summary

MonthPrint Success RateCommon IssuesOverall Assessment

Last log entry: __________ Logged by: __________

Command-Line Fundamentals - Choose Your Path

Welcome! Before diving into 3D design with OpenSCAD, you’ll master command-line fundamentals. This page will help you understand what command-line interfaces are and choose the best path for you.

What is a Command-Line Interface (CLI)?

A command-line interface is a text-based way to control your computer by typing commands instead of clicking buttons. It’s like sending written instructions to your computer.

Why learn it?

  • Speed: Text commands are often faster than clicking through menus
  • Precision: Exact control over what your computer does
  • Accessibility: Perfect for screen readers - text is naturally readable
  • Automation: Repeat tasks automatically
  • 3D Printing: Essential for batch processing models and integrating tools

Real-world example

Instead of:

  1. Opening File Explorer (click)
  2. Navigating folders (click, click, click)
  3. Right-clicking a file (click)
  4. Selecting “Copy” (click)
  5. Navigating to destination (click, click)
  6. Right-clicking (click)
  7. Selecting “Paste” (click)

You type: cp myfile.txt backup/ and press Enter. Done.

Three Command-Line Options on Windows

Windows offers three ways to use the command line. All are accessible with screen readers. Here’s how they compare:

Option 1: Windows Command Prompt (CMD)

What it is: The original Windows command-line (1981-present)

Best for: Absolute beginners, maximum simplicity

Pros:

  • Simple commands and syntax
  • Minimal learning curve
  • Easy to understand error messages
  • Great for basic file operations
  • Perfect entry point to command-line world

Cons:

  • Limited advanced features
  • Less powerful than alternatives
  • No built-in piping (but available)
  • Smaller ecosystem

Typical command:

copy myfile.txt backup\

Option 2: PowerShell

What it is: Microsoft’s modern, powerful shell (2006-present)

Best for: Intermediate users, advanced automation

Pros:

  • Very powerful for scripting
  • Modern syntax and features
  • Excellent for 3D printing automation
  • Professional workflows
  • Large community

Cons:

  • Steeper learning curve than CMD
  • More complex syntax
  • More “wordy” commands
  • Overkill for simple tasks

Typical command:

Copy-Item -Path myfile.txt -Destination backup/

Option 3: Git Bash

What it is: A Unix/Linux shell on Windows (runs bash inside Git for Windows)

Best for: Programmers, users familiar with Linux, advanced users

Pros:

  • Familiar if you know Linux/Unix
  • Powerful piping and text processing
  • Consistent with other platforms (macOS, Linux)
  • Excellent for advanced workflows
  • Industry-standard for developers

Cons:

  • Requires Git installation
  • Steeper learning curve
  • Path syntax is different from native Windows
  • Less integrated with Windows system tools
  • May be “too much” for beginners

Typical command:

cp myfile.txt backup/

Command Comparison Table

Here’s how common tasks compare across the three options:

TaskCommand PromptPowerShellGit Bash
Show current locationcdpwdpwd
List filesdir /Bls -nls
Go to foldercd Documentscd Documentscd Documents
Go up one levelcd ..cd ..cd ..
Go homecd %USERPROFILE%cd ~cd ~
Create foldermkdir Projectsmkdir Projectsmkdir Projects
Create fileecho text > file.txtecho "text" > file.txtecho "text" > file.txt
Copy filecopy old.txt new.txtCopy-Item old.txt new.txtcp old.txt new.txt
Move filemove old.txt folder/Move-Item old.txt folder/mv old.txt folder/
Delete filedel file.txtRemove-Item file.txtrm file.txt
List with filterdir /B *.txtls *.txtls *.txt
Save output to filedir > list.txtls > list.txtls > list.txt
Page through outputdir | morels | morels | less
Search in filesfindstr "text" file.txtSelect-String "text" file.txtgrep "text" file.txt
Show file contentstype file.txtcat file.txt or Get-Contentcat file.txt
Create script.bat files.ps1 files.sh files
Run scriptscript.bat.\script.ps1./script.sh

Feature Comparison Table

FeatureCMDPowerShellGit Bash
SimplicityEasiestModerateHardest
Beginner-FriendlyBestGoodChallenging
Power/CapabilityBasicExcellentExcellent
Screen Reader CompatiblePerfectPerfectPerfect
Linux/macOS SkillsWindows-onlySome overlapFull overlap
3D Printing AutomationAdequateExcellentAdequate
Learning CurveGentleModerateSteep
Community SupportModerateExcellentExcellent
Windows IntegrationPerfectPerfectGood
Installation DifficultyBuilt-inBuilt-inRequires Git

Quick Learner Profile Test

Answer these questions to find your best match:

Question 1: Experience Level

  • A: I’ve never used a command line Easier paths better (CMD or PowerShell)
  • B: I’ve used terminals before Any path works
  • C: I use macOS or Linux Git Bash most natural

Question 2: What matters most?

  • A: Simplicity and quick learning Choose CMD
  • B: Power and advanced features Choose PowerShell
  • C: Consistency across Windows/Mac/Linux Choose Git Bash

Question 3: Future goals

  • A: Just need to manage files for 3D printing CMD is fine
  • B: Advanced automation and scripting PowerShell recommended
  • C: Professional development workflows Git Bash best

Question 4: Your main concern

  • A: Don’t want steep learning curve CMD
  • B: Want industry-standard skills Git Bash
  • C: Want Microsoft’s modern tool PowerShell

Recommendation by Goal

Goal: “I want to learn the basics and get to 3D printing quickly”

Start with CMD (Command Prompt)

  • Simplest syntax
  • Fastest to get productive
  • All core concepts transfer to others
  • Can switch later if needed

Start CMD Foundation

Goal: “I want power and professional automation”

Start with PowerShell

  • Microsoft’s modern, recommended tool
  • Professional-grade capabilities
  • Better for complex 3D printing workflows
  • Skills are in-demand

Start PowerShell Foundation

Goal: “I want skills that work on Windows, Mac, and Linux”

Start with Git Bash

  • Unix/bash skills transfer everywhere
  • Great preparation for professional development
  • Consistent across all platforms
  • Growing standard in 3D printing tools

Start Git Bash Foundation

Can I Switch Paths Later?

Yes, absolutely! All three teach the same fundamental concepts:

  • File navigation and organization
  • Creating and managing files/folders
  • Combining commands for powerful workflows
  • Scripting and automation basics

Once you learn one, switching to another is quick. The concepts are identical; only the syntax changes.

Example: If you learn CMD first, then later want PowerShell’s power, you’ll find it easy. The command cd Documents works the same way in all three.

Important: All Are Equally Accessible

Screen readers work perfectly with all three

  • Text-based by nature (perfect for NVDA, JAWS)
  • No mouse required
  • Output is naturally readable
  • Keyboard-only workflows

Don’t let accessibility concerns influence your choice. All are fully accessible.

Getting Started: Your Decision

Take a moment and choose:

1. I want the simplest path

Command Prompt Foundation

  • Time to first success: ~30 minutes
  • Learning curve: Gentlest
  • When to upgrade: Once you’re comfortable and want power

2. I want modern, powerful Windows tools

PowerShell Foundation

  • Time to first success: ~45 minutes
  • Learning curve: Moderate
  • Best for: Professional automation, 3D printing workflows

3. I want Unix/Linux skills that work everywhere

Git Bash Foundation

  • Time to first success: ~1 hour
  • Learning curve: Steeper but rewarding
  • Best for: Professional development, cross-platform work

Not Sure? Here’s What Most People Do

If you’re reading this and unsure:

Start with Command Prompt (CMD). It’s the gentlest introduction. You’ll be productive quickly and can always switch to PowerShell or Git Bash later. The skills transfer completely.

After completing CMD:

  • Want more power? PowerShell is next
  • Want Linux skills? Git Bash is next
  • Want to stick with CMD? You have all the skills you need

FAQ

Q: Do I need to pick now and stick with it forever? A: No. Start with one, try another, switch between them. They’re tools. Use what works.

Q: Will my 3D printing skills work in all three? A: Yes. Once you understand the concepts (file organization, automation, piping), they apply everywhere.

Q: If I pick CMD, can I learn PowerShell later? A: Absolutely. Many learners do exactly this. CMD gets you productive; PowerShell adds power.

Q: Is Git Bash harder? A: Slightly, due to path syntax and Unix conventions. But not dramatically. If you take time with it, you’ll learn it.

Q: Which do professional 3D printing developers use? A: Mix of all three, but Git Bash/Linux is most common in cross-platform teams.

Ready to Begin?

Choose your path above and click to start. Remember:

  • Each lesson includes practice exercises
  • You can’t break anything
  • Mistakes are learning opportunities
  • Ask for help if stuck

Let’s get you comfortable with the command line!

Other Screen Readers

Dolphin SuperNova (commercial) and Windows Narrator (built-in) are also supported; the workflows and recommendations in this document apply to them. See https://yourdolphin.com/supernova/ and https://support.microsoft.com/narrator for vendor documentation.

Foundation of Command Line Tools — Complete Curriculum

Command-Line Fundamentals — Choose Your Path

Welcome! Before diving into 3D design with OpenSCAD, you’ll master command-line fundamentals. This page will help you understand what command-line interfaces are and choose the best path for you.

What is a Command-Line Interface (CLI)?

A command-line interface is a text-based way to control your computer by typing commands instead of clicking buttons. It’s like sending written instructions to your computer.

Why learn it?

  • Speed: Text commands are often faster than clicking through menus
  • Precision: Exact control over what your computer does
  • Accessibility: Perfect for screen readers - text is naturally readable
  • Automation: Repeat tasks automatically
  • 3D Printing: Essential for batch processing models and integrating tools

Real-world example

Instead of:

  1. Opening File Explorer (click)
  2. Navigating folders (click, click, click)
  3. Right-clicking a file (click)
  4. Selecting “Copy” (click)
  5. Navigating to destination (click, click)
  6. Right-clicking (click)
  7. Selecting “Paste” (click)

You type: cp myfile.txt backup/ and press Enter. Done.

Three Command-Line Options on Windows

Windows offers three ways to use the command line. All are accessible with screen readers. Here’s how they compare:

Option 1: Windows Command Prompt (CMD)

What it is: The original Windows command-line (1981-present)

Best for: Absolute beginners, maximum simplicity

Pros:

  • Simple commands and syntax
  • Minimal learning curve
  • Easy to understand error messages
  • Great for basic file operations
  • Perfect entry point to command-line world

Cons:

  • Limited advanced features
  • Less powerful than alternatives
  • No built-in piping (but available)
  • Smaller ecosystem

Typical command:

copy myfile.txt backup\

Option 2: PowerShell

What it is: Microsoft’s modern, powerful shell (2006-present)

Best for: Intermediate users, advanced automation

Pros:

  • Very powerful for scripting
  • Modern syntax and features
  • Excellent for 3D printing automation
  • Professional workflows
  • Large community

Cons:

  • Steeper learning curve than CMD
  • More complex syntax
  • More “wordy” commands
  • Overkill for simple tasks

Typical command:

Copy-Item -Path myfile.txt -Destination backup/

Option 3: Git Bash

What it is: A Unix/Linux shell on Windows (runs bash inside Git for Windows)

Best for: Programmers, users familiar with Linux, advanced users

Pros:

  • Familiar if you know Linux/Unix
  • Powerful piping and text processing
  • Consistent with other platforms (macOS, Linux)
  • Excellent for advanced workflows
  • Industry-standard for developers

Cons:

  • Requires Git installation
  • Steeper learning curve
  • Path syntax is different from native Windows
  • Less integrated with Windows system tools
  • May be “too much” for beginners

Typical command:

cp myfile.txt backup/

Command Comparison Table

Here’s how common tasks compare across the three options:

TaskCommand PromptPowerShellGit Bash
Show current locationcdpwdpwd
List filesdir /Bls -nls
Go to foldercd Documentscd Documentscd Documents
Go up one levelcd ..cd ..cd ..
Go homecd %USERPROFILE%cd ~cd ~
Create foldermkdir Projectsmkdir Projectsmkdir Projects
Create fileecho text > file.txtecho "text" > file.txtecho "text" > file.txt
Copy filecopy old.txt new.txtCopy-Item old.txt new.txtcp old.txt new.txt
Move filemove old.txt folder/Move-Item old.txt folder/mv old.txt folder/
Delete filedel file.txtRemove-Item file.txtrm file.txt
List with filterdir /B *.txtls *.txtls *.txt
Save output to filedir > list.txtls > list.txtls > list.txt
Page through outputdir | morels | morels | less
Search in filesfindstr "text" file.txtSelect-String "text" file.txtgrep "text" file.txt
Show file contentstype file.txtcat file.txt or Get-Contentcat file.txt
Create script.bat files.ps1 files.sh files
Run scriptscript.bat.\script.ps1./script.sh

Feature Comparison Table

FeatureCMDPowerShellGit Bash
SimplicityEasiestModerateHardest
Beginner-FriendlyBestGoodChallenging
Power/CapabilityBasicExcellentExcellent
Screen Reader CompatiblePerfectPerfectPerfect
Linux/macOS SkillsWindows-onlySome overlapFull overlap
3D Printing AutomationAdequateExcellentAdequate
Learning CurveGentleModerateSteep
Community SupportModerateExcellentExcellent
Windows IntegrationPerfectPerfectGood
Installation DifficultyBuilt-inBuilt-inRequires Git

Quick Learner Profile Test

Answer these questions to find your best match:

Question 1: Experience Level

  • A: I’ve never used a command line Easier paths better (CMD or PowerShell)
  • B: I’ve used terminals before Any path works
  • C: I use macOS or Linux Git Bash most natural

Question 2: What matters most?

  • A: Simplicity and quick learning Choose CMD
  • B: Power and advanced features Choose PowerShell
  • C: Consistency across Windows/Mac/Linux Choose Git Bash

Question 3: Future goals

  • A: Just need to manage files for 3D printing CMD is fine
  • B: Advanced automation and scripting PowerShell recommended
  • C: Professional development workflows Git Bash best

Question 4: Your main concern

  • A: Don’t want steep learning curve CMD
  • B: Want industry-standard skills Git Bash
  • C: Want Microsoft’s modern tool PowerShell

Recommendation by Goal

Goal: “I want to learn the basics and get to 3D printing quickly”

Start with CMD (Command Prompt)

  • Simplest syntax
  • Fastest to get productive
  • All core concepts transfer to others
  • Can switch later if needed

Start CMD Foundation — jump to Part 2 ↓

Goal: “I want power and professional automation”

Start with PowerShell

  • Microsoft’s modern, recommended tool
  • Professional-grade capabilities
  • Better for complex 3D printing workflows
  • Skills are in-demand

Start PowerShell Foundation — jump to Part 1 ↓

Goal: “I want skills that work on Windows, Mac, and Linux”

Start with Git Bash

  • Unix/bash skills transfer everywhere
  • Great preparation for professional development
  • Consistent across all platforms
  • Growing standard in 3D printing tools

Start Git Bash Foundation — jump to Part 3 ↓

Can I Switch Paths Later?

Yes, absolutely! All three teach the same fundamental concepts:

  • File navigation and organization
  • Creating and managing files/folders
  • Combining commands for powerful workflows
  • Scripting and automation basics

Once you learn one, switching to another is quick. The concepts are identical; only the syntax changes.

Example: If you learn CMD first, then later want PowerShell’s power, you’ll find it easy. The command cd Documents works the same way in all three.

Important: All Are Equally Accessible

Screen readers work perfectly with all three

  • Text-based by nature (perfect for NVDA, JAWS)
  • No mouse required
  • Output is naturally readable
  • Keyboard-only workflows

Note

All three shells — CMD, PowerShell, and Git Bash — work perfectly with NVDA, JAWS, Dolphin SuperNova, and Windows Narrator. Don’t let accessibility concerns influence your choice.

Don’t let accessibility concerns influence your choice. All are fully accessible.

Getting Started: Your Decision

Take a moment and choose:

1. I want the simplest path

Command Prompt Foundation — jump to Part 2 ↓

  • Time to first success: ~30 minutes
  • Learning curve: Gentlest
  • When to upgrade: Once you’re comfortable and want power

2. I want modern, powerful Windows tools

PowerShell Foundation — jump to Part 1 ↓

  • Time to first success: ~45 minutes
  • Learning curve: Moderate
  • Best for: Professional automation, 3D printing workflows

3. I want Unix/Linux skills that work everywhere

Git Bash Foundation — jump to Part 3 ↓

  • Time to first success: ~1 hour
  • Learning curve: Steeper but rewarding
  • Best for: Professional development, cross-platform work

Not Sure? Here’s What Most People Do

If you’re reading this and unsure:

Tip

Start with Command Prompt (CMD). It’s the gentlest introduction, and you’ll be productive quickly. You can always switch to PowerShell or Git Bash later — the concepts transfer completely.

After completing CMD:

  • Want more power? PowerShell is next
  • Want Linux skills? Git Bash is next
  • Want to stick with CMD? You have all the skills you need

FAQ

Q: Do I need to pick now and stick with it forever? A: No. Start with one, try another, switch between them. They’re tools. Use what works.

Q: Will my 3D printing skills work in all three? A: Yes. Once you understand the concepts (file organization, automation, piping), they apply everywhere.

Q: If I pick CMD, can I learn PowerShell later? A: Absolutely. Many learners do exactly this. CMD gets you productive; PowerShell adds power.

Q: Is Git Bash harder? A: Slightly, due to path syntax and Unix conventions. But not dramatically. If you take time with it, you’ll learn it.

Q: Which do professional 3D printing developers use? A: Mix of all three, but Git Bash/Linux is most common in cross-platform teams.

Ready to Begin?

Choose your path above and click to start. Remember:

  • Each lesson includes practice exercises

Tip

You can’t break your computer by typing a wrong command. The worst that happens is an error message. Mistakes are learning opportunities — just read the message and try again.

  • You can’t break anything
  • Mistakes are learning opportunities
  • Ask for help if stuck

Let’s get you comfortable with the command line!

Other Screen Readers

Dolphin SuperNova (commercial) and Windows Narrator (built-in) are also supported; the workflows and recommendations in this document apply to them. See https://yourdolphin.com/supernova/ and https://support.microsoft.com/narrator for vendor documentation.

Last Updated: February 2026 Total Duration: ~30–45 hours per track (screen reader users) Target Users: Anyone using a screen reader — NVDA, JAWS, Dolphin SuperNova, Windows Narrator

This combined curriculum covers three command-line environments taught in parallel. Each section follows the same lesson structure (Pre → 0 → 1 → 2 → 3 → 4 → 5 → 6 → Unit Exam) with shell-specific syntax and examples.


Master Table of Contents

Part 1 — PowerShell

SectionTitleTime
Screen Reader Accessibility GuideNVDA, JAWS, and terminal accessibility reference1.5 hrs
Lesson Pre: Your First TerminalOpening PowerShell, first commands, basic navigation2–2.5 hrs
Lesson 0: Getting StartedPaths, shortcuts, tab completion1.5 hrs
Lesson 1: NavigationMoving around the file system confidently2–2.5 hrs
Lesson 2: File and Folder ManipulationCreate, copy, move, delete files and folders2.5–3 hrs
Lesson 3: Input, Output, and PipingChain commands together, redirect output2.5–3 hrs
Lesson 4: Environment Variables and AliasesAutomate settings, create shortcuts2–2.5 hrs
Lesson 5: Filling in the GapsProfiles, history, debugging2–2.5 hrs
Lesson 6: Advanced TechniquesScripts, functions, loops, professional workflows4–4.5 hrs
Unit ExamComprehensive assessment — Lessons 0 through 660–90 min

Part 2 — Windows Command Prompt (CMD)

SectionTitleTime
Screen Reader Accessibility GuideNVDA, JAWS, Narrator, and SuperNova reference for CMD1.5 hrs
Lesson Pre: Your First TerminalOpening CMD, first commands, basic navigation1.5–2 hrs
Lesson 0: Getting StartedPaths, shortcuts, tab completion1.5 hrs
Lesson 1: NavigationMoving around the file system confidently2–2.5 hrs
Lesson 2: File and Folder ManipulationCreate, copy, move, delete files and folders2.5–3 hrs
Lesson 3: Input, Output, and PipingRedirect output, chain commands with pipes2.5–3 hrs
Lesson 4: Environment Variables and AliasesAutomate settings, create doskey shortcuts2–2.5 hrs
Lesson 5: Filling in the GapsAutorun scripts, history, debugging2–2.5 hrs
Lesson 6: Advanced TechniquesBatch scripts, subroutines, loops, professional workflows4–4.5 hrs
Unit ExamComprehensive assessment — Lessons 0 through 660–90 min

Part 3 — Git Bash

SectionTitleTime
Screen Reader Accessibility GuideNVDA, JAWS, Narrator, and SuperNova reference for Git Bash1–1.5 hrs
Tutorial: Git Bash Quick StartPrompt orientation, core commands, path concepts30–45 min
Lesson Pre: Your First TerminalInstalling Git Bash, opening it, first commands1.5–2 hrs
Lesson 0: Getting StartedPaths, ~, ./, ../, tab completion20–30 min
Lesson 1: Navigationpwd, cd, ls and flags, wildcards1 class period
Lesson 2: File and Folder Manipulationtouch, mkdir, cp, mv, rm, rmdir30–45 min
Lesson 3: Input, Output, and Pipingecho, cat, >, >>, |, clip, grep1 class period
Lesson 4: Environment Variables and Aliases$VARNAME, PATH, which, alias, .bashrc30–45 min
Lesson 5: Filling in the Gapshistory, Ctrl+R, .bashrc, ./30–45 min
Lesson 6: Advanced TechniquesShell scripts, functions, loops, professional workflows4–4.5 hrs
Unit ExamComprehensive assessment — Lessons 0 through 660–90 min

Quick Jump — By Lesson Across All Three Shells

LessonPowerShellCMDGit Bash
Accessibility GuidePSCMDGit Bash
Lesson PrePSCMDGit Bash
Lesson 0: Getting StartedPSCMDGit Bash
Lesson 1: NavigationPSCMDGit Bash
Lesson 2: File & Folder ManipulationPSCMDGit Bash
Lesson 3: Input, Output & PipingPSCMDGit Bash
Lesson 4: Environment VariablesPSCMDGit Bash
Lesson 5: Filling in the GapsPSCMDGit Bash
Lesson 6: Advanced TechniquesPSCMDGit Bash
Unit ExamPSCMDGit Bash

Part 1 — PowerShell


Last Updated: February 2026
Total Duration: 30–45 hours of instruction and practice (for screen reader users)
Target Users: Anyone using a screen reader (NVDA, JAWS, Dolphin SuperNova, Windows Narrator, or other)

This single file contains the complete PowerShell Foundation curriculum in reading order. All lessons, quizzes, extension problems, and the unit exam are included. No additional files are needed.


Table of Contents

SectionTitleEstimated Time
Screen Reader Accessibility GuideNVDA, JAWS, and terminal accessibility reference1.5 hours
Lesson Pre: Your First TerminalOpening PowerShell, first commands, basic navigation2–2.5 hours
Lesson 0: Getting StartedPaths, shortcuts, tab completion1.5 hours
Lesson 1: NavigationMoving around the file system confidently2–2.5 hours
Lesson 2: File and Folder ManipulationCreate, copy, move, delete files and folders2.5–3 hours
Lesson 3: Input, Output, and PipingChain commands together, redirect output2.5–3 hours
Lesson 4: Environment Variables and AliasesAutomate settings, create shortcuts2–2.5 hours
Lesson 5: Filling in the GapsProfiles, history, debugging2–2.5 hours
Lesson 6: Advanced TechniquesScripts, functions, loops, professional workflows4–4.5 hours
Unit ExamComprehensive assessment — Lessons 0 through 660–90 minutes

Total: approximately 30–45 hours including practice exercises


How to Use This File

If you have never used a terminal before: read from the top in order. Do not skip lessons — each builds on the one before it.

If you have used a terminal but not with a screen reader: start with the Accessibility Guide, skim Lesson Pre, then continue from Lesson 0.

If you are experienced with both: jump directly to the lesson you need. Use the quiz at the end of each lesson to self-test before moving on.

Reference while working: the Accessibility Guide and Lesson 0 contain material you will return to throughout the curriculum. Keep a copy open or bookmark those sections.


Curriculum Rules (Read These First)

Rule 1 — Always know where you are.
Every session, first thing: pwd. If you don’t know your path, you’ll get lost.

Rule 2 — Check before you delete.
Before any rm command: ls -n to confirm what you’re about to remove.

Rule 3 — Use -n with ls.
Always ls -n — never bare ls. The -n flag gives one name per line, which screen readers can follow.

Rule 4 — When lost, redirect to a file.
If output is confusing: command > output.txt then notepad.exe output.txt. This always works.

Rule 5 — Save everything you create.
Keep all practice files in a dedicated learning folder: mkdir ~/PS_Learning.



Screen Reader Accessibility Guide


Target Users: NVDA, JAWS, and other screen reader users
Last Updated: 2026

This guide supports the PowerShell Foundation curriculum and helps screen reader users navigate and work efficiently with PowerShell on Windows.

Table of Contents

  1. Getting Started with Screen Readers
  2. NVDA-Specific Tips
  3. JAWS-Specific Tips
  4. General Terminal Accessibility
  5. Working with Long Output
  6. Keyboard Shortcuts Reference
  7. Troubleshooting

Getting Started with Screen Readers

Which Screen Reader Should I Use?

NVDA is free and often recommended for new users; JAWS is a powerful commercial option. Also consider Dolphin SuperNova and Windows Narrator:

  • Dolphin SuperNova: commercial speech, braille and magnification (check vendor docs for keyboard mappings).
  • Windows Narrator: built into Windows and useful for quick access without installing third-party software.

Before You Start

  1. Start your screen reader before opening PowerShell.
  2. Open PowerShell and listen for the window title and prompt.
  3. If silent, press Alt+Tab to find the window.

What is PowerShell?

PowerShell is the modern Windows shell and scripting environment. Common commands include Get-ChildItem, Get-Content, and Out-File. PowerShell provides richer objects and piping than CMD.

NVDA-Specific Tips

NVDA is available from https://www.nvaccess.org/

Dolphin SuperNova

Dolphin SuperNova: https://yourdolphin.com/supernova/ — commercial option providing speech and magnification; consult vendor guides for features and commands.

Windows Narrator

Windows Narrator: https://support.microsoft.com/narrator — built-in Narrator has a different set of commands; it can be enabled via Windows Settings > Accessibility.

Key Commands for PowerShell

CommandWhat It Does
NVDA+HomeRead the current line (your command or output)
NVDA+Down ArrowRead from cursor to end of screen
NVDA+Up ArrowRead from top to cursor
NVDA+Page DownRead next page
NVDA+Page UpRead previous page
NVDA+F7Open the Review Mode viewer (can scroll through text)

Example: Reading Long Output

If Get-ChildItem produces many lines, redirect to a file and open it in Notepad:

Get-ChildItem -Name > list.txt
notepad list.txt

-Name prints one item per line (screen reader friendly).

JAWS-Specific Tips

JAWS is available from https://www.freedomscientific.com/

Key Commands for PowerShell

CommandWhat It Does
Insert+Down ArrowRead line by line downward
Insert+Up ArrowRead line by line upward
Insert+Page DownRead next page of text
Insert+Page UpRead previous page of text

Example: Reading Long Output

  1. Redirect: Get-ChildItem -Name > list.txt
  2. Open Notepad: notepad list.txt
  3. Use Insert+Ctrl+Down to read full contents.

General Terminal Accessibility

Understanding the PowerShell Layout

PowerShell shows a title bar, content area, and a prompt that looks like:

PS C:\Users\YourName>
  1. Screen reader announces the title
  2. Then it announces the prompt line
  3. Anything above prompt is prior output

Working with Long Output

Solution 1: Redirect to a File

Get-ChildItem -Name > list.txt
notepad list.txt

Solution 2: Use Pagination

Get-Content largefile.txt | more

Solution 3: Filter Output

Get-ChildItem -Name | Where-Object { $_ -like "*.scad" }

Solution 4: Count Before Displaying

(Get-ChildItem -Name).Count

Keyboard Shortcuts Reference

KeyAction
Up ArrowShow previous command
Down ArrowShow next command
TabAuto-complete file/folder names
HomeJump to start of line
EndJump to end of line
Ctrl+CStop command
EnterRun command

Troubleshooting

Problem: “I Can’t Hear the Output”

  1. Redirect to file and open in Notepad.
  2. Use End to jump to the end of text.

Problem: “Tab Completion Isn’t Working”

  1. Type some characters before Tab.

Problem: “Command Not Found”

  1. Use Get-Command programname to check availability.

Pro Tips

  1. Use Get-ChildItem -Name for one-per-line listings.
  2. Use Out-File -FilePath list.txt to capture output with encoding options.
  1. Set-Location (or cd) to the project folder
  2. Get-ChildItem -Name to list files
  3. Redirect large output to files and open in Notepad

Additional Resources


Lesson Pre: Your First Terminal


Duration: 1.5-2 hours (for screen reader users)
Prerequisites: None - this is the starting point
Accessibility Note: This lesson is designed specifically for screen reader users (NVDA, JAWS)

What is a Terminal?

A terminal (also called a command line or shell) is a text-based interface where you type commands instead of clicking buttons. Think of it like sending written instructions to your computer instead of pointing and clicking.

Why learn this?

  • Faster and more precise work (especially for 3D printing scripts and automation)
  • Essential for programming and using tools like OpenSCAD
  • Accessibility: Many command line tools work perfectly with screen readers
  • Scripting: Automate repetitive tasks

Opening PowerShell for the First Time

3DMake: Your First Real-World Goal

3DMake (github.com/tdeck/3dmake) is a free, accessibility-first command-line tool for designing and 3D-printing models entirely from the terminal — no mouse required. Every PowerShell skill in this curriculum directly supports a real 3DMake workflow.

Here is the end goal — one command that builds your OpenSCAD model, slices it, and sends it to the printer:

# Navigate to your project folder
cd ~/Documents/3d_projects/my_cube

# Build, slice, and print in a single command
3dm build slice print

Keep this goal in mind as you work through each lesson.

Opening PowerShell for the First Time

On Windows

Method 1: Search (Easiest)

  1. Press the Windows key alone
  2. You should hear “Search”
  3. Type: PowerShell
  4. You’ll hear search results appear
  5. Press Enter to open the first result (Windows PowerShell)
  6. PowerShell will open in a new window

Method 2: Using the Start Menu

  1. Press Windows key + X (opens the Quick Link menu)
  2. Look for “Windows PowerShell” or “Terminal”
  3. Press Enter

Method 3: From File Explorer

  1. Open File Explorer
  2. Navigate to any folder
  3. In the menu bar, select “File” -> “Open Windows PowerShell here”
  4. PowerShell opens in that folder location

First Connection: Understanding the Prompt

When PowerShell opens, your screen reader will announce the window title and then the prompt. The prompt is where you type commands.

What you’ll hear:

PS C:\Users\YourName>

What this means:

  • PS = “PowerShell” indicator
  • C:\Users\YourName = Your current location (the “path”)
  • > = The prompt is ready for your input

Important

Your cursor is blinking right after the >. This is where you type.

Your First Commands (Screen Reader Edition)

Command 1: “Where Am I?” - pwd

What it does: Tells you your current location

Type this:

pwd

Press Enter

What you’ll hear: Your screen reader will announce the current path, something like:

C:\Users\YourName

Understanding paths:

  • Paths show your location in the file system (like a mailing address)
  • Windows paths use backslashes: C:\Users\YourName\Documents
  • Think of it like folders inside folders: C:\ (main drive) -> Users -> YourName -> Documents

Command 2: “What’s Here?” - ls -n

What it does: Lists all files and folders in your current location. The -n flag makes it screen-reader friendly (names only, one per line)

Type this:

ls -n

Press Enter

What you’ll hear: Your screen reader will announce each file and folder name, one per line:

Desktop
Documents
Downloads
Music
Pictures
...

Why -n?

  • Without -n, PowerShell shows files in columns (hard to read with a screen reader)
  • With -n, each file/folder is on its own line (perfect for screen readers)

Command 3: “Go There” - cd Documents

What it does: Changes your location (navigates to a folder)

Type this:

cd Documents

Press Enter

What you’ll hear: The prompt changes to show your new location. You might hear something like:

PS C:\Users\YourName\Documents>

Practice navigation:

  1. Run pwd to confirm you’re in Documents
  2. Run ls -n to see what files are in Documents
  3. Try going back: cd .. (the .. means “go up one level”)
  4. Run pwd again to confirm
  5. Go back to Documents: cd Documents

Reading Screen Reader Output (Critical Skills)

Dealing with Long Lists

When you run ls -n in a folder with many files, the list might be very long. Your screen reader might announce 50+ items rapidly.

Solution 1: Save to a File

ls -n > list.txt
notepad.exe list.txt

This saves the list to a file and opens it in Notepad where you can read it more slowly.

Solution 2: Search Within the Output

ls -n | findstr "search-term"

Example: If you’re looking for files containing “scad”, type:

ls -n | findstr "scad"

One of the most powerful screen reader tricks is Tab completion:

How it works:

  1. Type the first few letters of a folder or file name
  2. Press Tab
  3. PowerShell automatically completes the rest

Example:

  1. You’re in C:\Users\YourName>
  2. Type: cd Doc
  3. Press Tab
  4. PowerShell auto-completes it to: cd Documents
  5. Press Enter to go there

With a screen reader:

  1. As you type Doc, your screen reader announces each letter
  2. When you press Tab, PowerShell types the rest and your screen reader announces the full command
  3. This is much faster than typing the whole thing

Creating and Editing Files

Create a Simple File

Type this:

echo "Hello, PowerShell!" > hello.txt

What this does:

  • echo sends text to the screen (or file)
  • "Hello, PowerShell!" is the text
  • > redirects it to a file called hello.txt

Read the File Back

Type this:

cat hello.txt

What you’ll hear: Your screen reader announces:

Hello, PowerShell!

Open and Edit the File

Type this:

notepad.exe hello.txt

This opens the file in Notepad where you can edit it with your screen reader.

Essential Keyboard Shortcuts

These work in PowerShell and are crucial for screen reader users:

Key CombinationWhat It Does
Up ArrowShows your previous command (press again to go further back)
Down ArrowShows your next command (if you went back)
TabAuto-completes folder/file names

Important

Ctrl+C stops any running command immediately. If a command seems frozen or is producing endless output, press Ctrl+C to regain control of the prompt.

| Ctrl+C | Stops a running command | | Ctrl+L | Clears the screen | | Enter | Runs the command |

Screen reader tip: These all work perfectly with your screen reader. Try them!

Screen Reader-Specific Tips

NVDA Users

  1. Reading Command Output:

    • Use NVDA+Home to read the current line
    • Use NVDA+Down Arrow to read to the end of the screen
    • Use NVDA+Page Down to read the next page
  2. Reviewing Text:

    • Use NVDA+Shift+Page Up to review text above

JAWS Users

  1. Reading Output:

    • Use Insert+Down Arrow to read line-by-line
    • Use Insert+Page Down to read by page
    • Use Insert+End to jump to the end of text
  2. Reading All Text:

    • Use Insert+Down Arrow repeatedly
    • Or use Insert+Ctrl+Down to read to the end

Common Issue: “I Can’t Hear the Output”

Problem: You run a command but don’t hear the output

Solutions:

  1. Make sure your cursor is at the prompt (try pressing End or Ctrl+End)
  2. Use Up Arrow to go back to your previous command and review it
  3. Try redirecting to a file: command > output.txt then open the file
  4. In NVDA: Try pressing NVDA+F7 to open the Review Mode viewer

Practice Exercises

Complete these in order. Take your time with each one:

Exercise 1: Basic Navigation

  1. Open PowerShell
  2. Run pwd and note your location
  3. Run ls -n and listen to what’s there
  4. Try cd Documents or another folder
  5. Run pwd to confirm your new location
  6. Run ls -n in this new location

Goal: You should be comfortable knowing where you are and what’s around you

Exercise 2: Using Tab Completion

  1. In your home directory, type cd D (just the letter D)
  2. Press Tab
  3. PowerShell should auto-complete to a folder starting with D
  4. Repeat with other folder names
  5. Try typing a longer name: cd Down and Tab to Downloads

Goal: Tab completion should feel natural

Exercise 3: Creating and Viewing Files

  1. Create a file: echo "Test content" > test.txt
  2. View it: cat test.txt
  3. Create another: echo "Line 2" > another.txt
  4. List both: ls -n

Goal: You understand create, view, and list operations

Exercise 4: Going Up Levels

  1. Navigate into several folders: cd Documents, then cd folder1, etc.
  2. From deep inside, use cd .. multiple times to go back up
  3. After each cd .., run pwd to confirm your location

Goal: You understand relative navigation with ..

Exercise 5: Redirecting Output

  1. Create a list: ls -n > directory_list.txt
  2. Open it: notepad.exe directory_list.txt
  3. Read it with your screen reader
  4. Close Notepad
  5. Verify the file exists: ls -n | findstr "directory"

Goal: You can save long outputs to files for easier reading

Checkpoint Questions

After completing this lesson, you should be able to answer:

  1. What does pwd do?
  2. What does ls -n do?
  3. Why do we use -n with ls?
  4. What path are you in right now?
  5. How do you navigate to a new folder?
  6. How do you go up one level?
  7. What’s the Tab key for?
  8. What does echo "text" > file.txt do?
  9. How do you read a file back?
  10. How do you stop a command that’s running?

You should be able to answer all 10 with confidence before moving to Lesson 0.

Common Questions

Q: Do I need to use PowerShell? Can I use Command Prompt (cmd.exe)? A: PowerShell is more powerful and works better with modern tools. We recommend PowerShell, but Command Prompt basics are similar.

Tip

If your screen reader isn’t announcing terminal output, use command > file.txt to save output to a file, then open it with notepad.exe file.txt for reliable reading. This trick works with all four screen readers throughout the curriculum.

Q: Why is my screen reader not reading the output? A: This is common. Use command > file.txt to save output to a file, then open it with Notepad for reliable reading.

Q: What if I type something wrong? A: Just press Enter and you’ll see an error message. Type the correct command on the next line. No harm done!

Q: How do I get help with a command? A: Type Get-Help command-name (we’ll cover this in Lesson 0)

Q: Can I make PowerShell more accessible? A: Yes! We’ll cover customization in Lesson 5.

Next Steps

Once you’re comfortable with these basics:

  • Move to Lesson 0: Getting Started for deeper path understanding
  • Then continue through Lessons 1–5 for full terminal mastery

Resources

Troubleshooting

IssueSolution
PowerShell won’t openTry searching Windows, or right-click a folder and select “Open PowerShell here”
Can’t hear the outputTry redirecting to a file: command > output.txt
Tab completion not workingMake sure you typed at least one character before pressing Tab
Command not foundMake sure you spelled it correctly; try Get-Command to see available commands
Stuck in a commandPress Ctrl+C to stop it

Still stuck? The checkpoint questions and exercises are your best teacher. Work through them multiple times until comfortable.

Other Screen Readers

Dolphin SuperNova (commercial) and Windows Narrator (built-in) are also supported; the workflows and recommendations in this document apply to them. See https://yourdolphin.com/supernova/ and https://support.microsoft.com/narrator for vendor documentation.


Lesson 0: Getting Started — Layout, Paths, and the Shell


Estimated time: 20-30 minutes

Learning Objectives

  • Launch PowerShell and locate the prompt
  • Understand path notation and shortcuts (~, ./, ../)
  • Use tab completion to navigate quickly

Materials

  • Computer with PowerShell
  • Editor (Notepad/VS Code)

Step-by-step Tasks

  1. Open PowerShell and note the prompt (it includes the current path).
  2. Run pwd and say or note the printed path.
  3. Use ls -n to list names in your home directory.
  4. Practice cd Documents, cd ../ and cd ~ until comfortable.
  5. Try tab-completion: type cd ~/D and press Tab.

Checkpoints

  • Confirm you can state your current path and move to Documents.

Quiz - Lesson PS.0

3DMake Quick-Start: Your First Real Project

You now know enough PowerShell to set up a real 3DMake project. Do this now — it is the fastest path to a printed object.

Step 1 — Download and run the 3DMake setup wizard:

# Go to your Downloads folder (where you extracted 3dmake_windows.zip)
cd ~/Downloads/3dmake

# Run the guided setup (answer the questions about your printer)
./3dm setup

Step 2 — Create your first project:

# Create a folder for all your 3D projects
mkdir ~/Documents/3d_projects

# Create your first project folder and initialize it
mkdir ~/Documents/3d_projects/my_cube
cd ~/Documents/3d_projects/my_cube
3dm new

Step 3 — Confirm the project structure:

# You should see three items: src, build, and 3dmake.toml
ls -n

You just used mkdir, cd, and ls -n on a real project. You are ready to print.

Checkpoints

  • Confirm you can state your current path and move to Documents.

Quiz - Lesson PS.0

  1. What is a path?
  2. What does ~ mean?
  3. How do you autocomplete a path?
  4. How do you go up one directory?
  5. What command lists only names (ls flag)?
  6. True or False: On Windows, PowerShell uses backslashes (\) in paths, but forward slashes (/) are also accepted.
  7. Explain the difference between an absolute path and a relative path.
  8. If you are in C:\Users\YourName\Documents and you type cd ../, where do you end up?
  9. What happens when you press Tab while typing a folder name in PowerShell?
  10. Describe a practical reason why understanding paths is important for a 3D printing workflow.
  11. What does ./ mean in a path, and when would you use it?
  12. If a folder path contains spaces (e.g., Program Files), how do you navigate to it with cd?
  13. Explain what the prompt PS C:\Users\YourName> tells you about your current state.
  14. How would you navigate to your home directory from any location using a single command?
  15. What is the advantage of using relative paths (like ../) versus absolute paths in automation scripts?

Extension Problems

  1. Create a nested folder and practice cd into it by typing partial names and using Tab.
  2. Use ls -n -af to list only files in a folder.
  3. Save pwd output to a file and open it in Notepad.
  4. Try cd into a folder whose name contains spaces; observe how quotes are handled.
  5. Create a short note file and open it from PowerShell.
  6. Build a folder structure that mirrors your project organization; navigate to each level and document the path.
  7. Create a script that prints your current path and the total number of files in it; run it from different locations.
  8. Investigate the special paths (e.g., $HOME, $PSScriptRoot); write down what each contains and when you’d use them.
  9. Compare absolute vs. relative paths by navigating to the same folder using each method; explain which is easier for automation.
  10. Create a PowerShell function that changes to a frequently-used folder and lists its contents in one command; test it from different starting locations.
  11. Navigate to three different locations and at each one note the prompt, the path from pwd, and verify you understand what each shows.
  12. Create a complex folder tree (at least 5 levels deep) and navigate it using only relative paths; verify your location at each step.
  13. Document all shortcuts you know (~, ./, ../, $HOME) and demonstrate each one works as expected.
  14. Write a guide for a peer on how to understand the PowerShell prompt and path notation without using GUI file explorer.
  15. Create a troubleshooting flowchart: if someone says “I don’t know where I am,” what commands do you give them to find out?

References

Helpful Resources


Lesson 1: Navigation — Moving Around Your File System


Duration: 1 class period
Prerequisite: Lesson 0 (Getting Started)

Learning Objectives By the end of this lesson, you will be able to:

  • Use pwd to print your current location
  • Use cd to move between directories
  • Use ls (and its flags) to list files and folders
  • Use wildcards * and ? to filter listings
  • Navigate relative vs. absolute paths
  • Search for files by name and extension

Materials

  • PowerShell
  • Text editor (Notepad or VS Code)

Commands Covered in This Lesson

CommandWhat It Does
pwdPrint Working Directory - shows where you are
cd pathChange Directory - move to a new location
lsList - shows files and folders in current location
ls -nList names only (screen reader friendly)
ls -n -afList names of files only
ls -n -adList names of directories only
ls *.extensionList files matching a pattern

pwd - Where Am I?

Type pwd and press Enter. PowerShell prints the full path to your current location.

pwd
# Output: C:\Users\YourName

When to use: Always run this if you’re unsure of your current location.

cd - Changing Directories

cd stands for “change directory.”

# Go to Documents
cd Documents
# Go up one level to parent directory
cd ..
# Go to home directory
cd ~
# Go to a specific path
cd C:\Users\YourName\Documents\3D_Projects

ls - Listing Files and Folders

Use ls -n for screen reader compatibility.

# List all files and folders (names only)
ls -n
# List only files (no folders)
ls -n -af
# List only folders (no files)
ls -n -ad

Wildcards - Finding Files by Pattern

Wildcards help you find files without typing the full name.

* (asterisk) matches any number of characters:

# List all .scad files
ls -n *.scad
# List all files starting with "part"
ls -n part*
# List all files ending with "_final"
ls -n *_final*

? (question mark) matches exactly one character:

# Find files like model1.scad, model2.scad (but not model12.scad)
ls -n model?.scad

Step-by-step Practice

3DMake in Practice: Navigating a Project

Navigation commands are exactly what you need to explore and manage 3DMake projects:

# Go to your project root
cd ~/Documents/3d_projects/my_cube

# See the project layout: src/, build/, 3dmake.toml
ls -n

# Enter the source folder where your .scad model files live
cd src
ls -n

# Open the main model in your text editor
3dm edit-model

# Go back to project root, then check the build output
cd ..
cd build
ls -n *.stl        # list any STL files already built

# Return to project root
cd ..

# Use wildcards to find all projects with "cube" in the name
ls -n ~/Documents/3d_projects/*cube*

Tab completion makes navigation fast: type cd ~/Doc and press Tab.

Step-by-step Practice

  1. Run pwd and confirm your location
  2. Move to Documents: cd Documents
  3. Confirm you moved: pwd
  4. List files and folders: ls -n
  5. List only files: ls -n -af
  6. Go back up: cd ..
  7. Search for files: ls -n *.txt

Checkpoints

After this lesson, you should be able to:

  • Navigate to any folder using cd
  • Confirm your location with pwd
  • List files and folders with ls -n
  • Use wildcards to find files by pattern
  • Move between absolute and relative paths confidently

Quiz - Lesson PS.1

  1. What does pwd show?
  2. How do you list directories only with ls?
  3. What wildcard matches any number of characters?
  4. How do you list files with the .scad extension?
  5. Give an example of an absolute path and a relative path.
  6. True or False: The * wildcard matches exactly one character.
  7. Explain the difference between ls -n and ls -n -ad.
  8. Write a command that would list all .txt files in your Documents folder using a wildcard.
  9. How would you search for files containing “part” in their name across multiple files?
  10. Describe a practical scenario where using wildcards saves time in a 3D printing workflow.
  11. What happens when you use ls -n part?.scad versus ls -n part*.scad?
  12. How would you navigate to a folder whose name contains both spaces and special characters?
  13. If you’re in /Documents/Projects/3D and you want to go to /Documents/Resources, what command would you use?
  14. Write a command sequence that navigates to the Downloads folder, lists only files, then returns to home.
  15. Explain the purpose of using ls -n -af specifically in a screen reader context.

Extension Problems

  1. Write a one-line script that lists .scad files and saves to scad_list.txt.
  2. Use ls -n ~/Documents | more to page through long listings.
  3. Combine ls with Select-String to search for a filename pattern.
  4. Create a shortcut alias in the session for a long path and test it.
  5. Practice tab-completion in a directory with many similarly named files.
  6. Build a PowerShell script that recursively lists all .scad and .stl files in a directory tree; save the results to a file.
  7. Compare the output of ls, Get-ChildItem, and gci to understand PowerShell aliasing; document what each command does.
  8. Create a filtering command that displays only files modified in the last 7 days; test it on your documents folder.
  9. Write a non-visual guide to PowerShell navigation; include descriptions of common patterns and how to verify directory contents audibly.
  10. Develop a navigation workflow for a typical 3D printing project: move between CAD, slicing, and print-log folders efficiently; document the commands.
  11. Create a complex wildcard search: find all files in a folder and subfolders that match multiple patterns (e.g., *_v1.* OR *_final.*).
  12. Build a script that navigates through a folder tree, counts files at each level, and reports the structure.
  13. Document the output differences between ls -n, ls -n -af, ls -n -ad, and Get-ChildItem; explain when to use each.
  14. Create a navigation “cheat sheet” as a PowerShell script that prints common paths and how to navigate to them.
  15. Design a project folder structure on your computer, document each path, then create a script that validates all folders exist.

References

Helpful Resources


Lesson 2: File and Folder Manipulation


Estimated time: 30-45 minutes

Learning Objectives

  • Create, copy, move, and delete files and folders from PowerShell
  • Use ni, mkdir, cp, mv, rm, and rmdir safely
  • Understand when operations are permanent and how to confirm results

Materials

  • PowerShell
  • Small practice folder for exercises

Step-by-step Tasks

  1. Create a practice directory: mkdir ~/Documents/PS_Practice and cd into it.
  2. Create two files: ni file1.txt and ni file2.txt.
  3. Copy file1.txt to file1_backup.txt with cp and confirm with ls -n.
  4. Rename file2.txt to notes.txt using mv and confirm.
  5. Delete file1.txt with rm and verify the backup remains.

Checkpoints

  • After step 3 you should see both the original and the backup file.

3DMake in Practice: Organizing Your Projects

File management commands are essential for 3DMake project organization:

# Create a new project from scratch
mkdir ~/Documents/3d_projects/bottle_cap
cd ~/Documents/3d_projects/bottle_cap
3dm new

# Back up a working project before making big changes
cd ~/Documents/3d_projects
cp -r bottle_cap bottle_cap_backup

# Rename the main model file to something more specific
cd bottle_cap/src
mv main.scad bottle_cap.scad

# List only .scad files to confirm the rename
ls -n *.scad

# Delete a draft STL you no longer need
rm ~/Documents/3d_projects/bottle_cap/build/draft.stl

# Now build the renamed model (using the -m flag to specify the name)
cd ~/Documents/3d_projects/bottle_cap
3dm build -m bottle_cap

# See the fresh output in the build folder
ls -n build/

Checkpoints

  • After step 3 you should see both the original and the backup file.

Quiz - Lesson PS.2

  1. How do you create an empty file from PowerShell?
  2. What command copies a file?
  3. How do you rename a file?
  4. What does rm -r do?
  5. Why is rm potentially dangerous?
  6. True or False: cp requires the -r flag to copy both files and folders.
  7. Explain the difference between rm and rmdir.
  8. If you delete a file with rm, can you recover it from PowerShell?
  9. Write a command that would copy an entire folder and all its contents to a new location.
  10. Describe a practical safety check you would perform before running rm -r on a folder.

Caution

By default, cp silently overwrites an existing file at the destination with no warning. Use cp -i (interactive) to get a confirmation prompt before overwriting, especially when working with important files.

  1. What happens if you cp a file to a destination where a file with the same name already exists? How would you handle this safely?
  2. Compare mv old_name.txt new_name.txt vs mv old_name.txt ~/Documents/new_name.txt. What is the key difference?
  3. Design a workflow to safely delete 50 files matching the pattern *.bak from a folder containing 500 files. What commands and verifications would you use?
  4. Explain how you could back up all .scad files from a project folder into a timestamped backup folder in one command.
  5. When organizing a 3D printing project, you need to move completed designs to an archive folder and delete failed prototypes. How would you structure this as a safe, auditable process?

Extension Problems

  1. Create a folder tree and copy it to a new location with cp -r.
  2. Write a one-line command that creates three files named a b c and lists them.
  3. Move a file into a new folder and confirm the move.
  4. Use wildcards to delete files matching a pattern in a safe test folder.
  5. Export a listing of the practice folder to practice_listing.txt.
  6. Create a backup script that copies all .scad files from your project folder to a backup folder with timestamp naming.
  7. Build a safe deletion workflow: list files matching a pattern, verify count, then delete with confirmation; document the steps.
  8. Write a PowerShell script that organizes files by extension into subfolders; test it on a sample folder tree.
  9. Create a file operation audit trail: log all copy, move, and delete operations to a text file for review.
  10. Develop a project template generator: a script that creates a standard folder structure for a new 3D printing project with essential subfolders.
  11. Implement a file conflict handler: write a script that handles cases where cp would overwrite an existing file by renaming the existing file with a timestamp before copying.
  12. Create a batch rename operation: use a script to rename all files in a folder from old_prefix_* to new_prefix_*; test with actual files and verify the results.
  13. Build a folder comparison tool: list all files in two folders and identify which files exist in one but not the other; output to a report.
  14. Write a destructive operation validator: before executing rm -r, create a script that lists exactly what will be deleted, shows file counts by type, and requires explicit user confirmation to proceed.
  15. Design a complete project lifecycle workflow: create folders for active projects, completed designs, and archive; include move operations between folders, backup steps, and verification that all files arrive intact.

References

Helpful Resources


Lesson 3: Input, Output, and Piping


Duration: 1 class period Prerequisite: Lesson 2 (File and Folder Manipulation)

Learning Objectives

By the end of this lesson, you will be able to:

  • Use echo to print text to the screen
  • Use cat to read file contents
  • Use > to redirect output into a file
  • Use | (pipe) to send one command’s output to another
  • Copy output to the clipboard with clip
  • Open files with a text editor from the command line

Commands Covered

CommandWhat It Does
echo "text"Print text to the screen
cat filenamePrint the contents of a file
> filenameRedirect output into a file (overwrites)
>> filenameAppend output to a file (adds to end)
|Pipe - send output from one command to the next
clipCopy piped input to the Windows clipboard
notepad.exe filenameOpen a file in Notepad

echo - Printing Text

echo prints text to the screen. It is useful for testing, for writing text into files, and for understanding how piping works.

echo "Hello, World"
echo "This is a test"

cat - Reading Files

cat prints the contents of a file to the screen.

# Read a text file
cat ~/Documents/notes.txt
# Read an OpenSCAD file
cat ~/Documents/OpenSCAD_Projects/project0.scad

With a long file, use cat filename | more to read it page by page (press Space to advance, Q to quit).

> - Redirecting Output to a File

The > symbol redirects output from the screen into a file instead.

# Create a file with a single line
echo "Author: Your Name" > header.txt
# Confirm the file was created and has content
cat header.txt

Warning

> overwrites the file if it already exists. Use >> to append instead:

echo "Date: 2025" >> header.txt
echo "Project: Floor Marker" >> header.txt
cat header.txt

| - Piping

The pipe symbol | sends the output of one command to the input of the next. This lets you chain commands together.

# List files and send the list to clip (copies to clipboard)
ls -n | clip
## 3DMake in Practice: Capturing Build Output

Piping and redirection are essential for working with 3DMake's output accessibly:

```powershell
# Build and save the full log to a file so you can read it in Notepad
3dm build > build_log.txt
notepad.exe build_log.txt

# Build and slice, keeping only lines with errors or warnings
3dm build slice 2>&1 | Select-String -Pattern "error|warning" -CaseSensitive:$false

# List all STL files produced so far
ls -n build/ | findstr ".stl"

# Get a list of available printer profiles and save for reference
3dm list-profiles > profiles.txt
notepad.exe profiles.txt

# Get a list of material overlays (PLA, PETG, supports, etc.)
3dm list-overlays > overlays.txt
notepad.exe overlays.txt

# Get an AI description of your model and save it
3dm info > model_description.txt
notepad.exe model_description.txt
# List files and send the list to clip (copies to clipboard)
ls -n | clip
# Now paste with Ctrl + V anywhere
# Search within a file's contents using Select-String (like grep)
cat project0.scad | Select-String "cube"

clip - Copying to Clipboard

clip takes whatever is piped to it and puts it on the Windows clipboard.

# Copy your current directory path to the clipboard
pwd | clip
# Copy a file listing to clipboard
ls -n | clip
# Copy the contents of a file to clipboard
cat notes.txt | clip

After any of these, press Ctrl + V in any application to paste.

Opening Files in Notepad

# Open a file in Notepad
notepad.exe ~/Documents/notes.txt
# Open a .scad file
notepad.exe ~/Documents/OpenSCAD_Projects/project0.scad
# Create a new file and open it
notepad new_notes.txt

Step-by-step Tasks

  1. Create practice.txt with three lines using echo and >/>>.
  2. Read the file with cat practice.txt.
  3. Pipe the file into Select-String to search for a word.
  4. Copy the file contents to clipboard with cat practice.txt | clip.
  5. Redirect ls -n into list.txt and open it in Notepad. Checkpoints
  • After step 3 you should be able to find a keyword using piping.

Quiz - Lesson PS.3

  1. What is the difference between > and >>?
  2. What does the pipe | do?
  3. How do you copy output to the clipboard?
  4. How would you page through long output?
  5. How do you suppress output to nowhere?
  6. True or False: The pipe operator | connects the output of one command to the input of another.
  7. Explain why redirecting output to a file is useful for screen reader users.
  8. Write a command that would search for the word “sphere” in all .scad files in a directory.
  9. How would you count the number of lines in a file using PowerShell piping?
  10. Describe a practical scenario in 3D printing where you would pipe or redirect command output.
  11. What would be the difference in output between echo "test" > file.txt (run twice) vs echo "test" >> file.txt (run twice)? Show the expected file contents.
  12. Design a three-step piping chain: read a file, filter for specific content, and save the results; explain what each pipe does.
  13. You have a 500-line .scad file and need to find all instances of sphere() and count them. Write the command.
  14. Explain how clip is particularly valuable for screen reader users when working with file paths or long output strings.
  15. Describe how you would use pipes and redirection to create a timestamped backup report of all .stl files in a 3D printing project folder.

Extension Problems

  1. Use piping to count lines in a file (hint: Select-String -Pattern '.' | Measure-Object).
  2. Save a long ls -n output and search it with Select-String.
  3. Chain multiple pipes to filter and then save results.
  4. Practice copying different command outputs to clipboard and pasting.
  5. Create a small script that generates a report (counts of files by extension).
  6. Build a data processing pipeline: read a CSV file, filter rows, and export results; document each step.
  7. Write a script that pipes directory listing to Count occurrences of each file extension; create a summary report.
  8. Create a log analysis command: read a log file, filter for errors, and save matching lines to a separate error log.
  9. Design a piping workflow for 3D printing file management: find .stl files, extract their sizes, and generate a report.
  10. Develop a reusable piping function library: create functions for common filtering, sorting, and reporting patterns; test each function with different inputs.
  11. Build a complex filter pipeline: read a .scad file, extract lines containing specific geometry commands, count each type, and output a summary to both screen and file.
  12. Create an interactive piping tool: build a script that accepts user input for a search term, pipes through multiple filters, and displays paginated results.
  13. Develop a performance analysis tool: use piping to combine file listing, metadata extraction, and statistical reporting; export results to a dated report file.
  14. Implement a comprehensive error-handling pipeline: read output, catch errors, log them separately, and generate a summary of successes vs failures.
  15. Design and execute a real-world project backup workflow: use piping to verify file integrity, count files by type, generate a backup manifest, and create audit logs-all in one integrated command pipeline.

References

Helpful Resources


Lesson 4: Environment Variables, PATH, and Aliases


Estimated time: 30-45 minutes

Learning Objectives

  • Read environment variables with $env:VARNAME
  • Inspect and verify programs in the PATH
  • Create temporary aliases and understand making them persistent via the profile

Materials

  • PowerShell (with rights to open profile if desired)

Step-by-step Tasks

  1. Show your username and home path with echo $env:USERNAME and echo $env:USERPROFILE.
  2. Inspect echo $env:PATH and identify whether openscad or code would be found.
  3. Run Get-Command openscad and note the result.
  4. Create a temporary alias: Set-Alias -Name preview -Value openscad and test preview myfile.scad.
  5. Open your profile (notepad.exe $PROFILE) and add the alias line to make it persistent (advanced).

Checkpoints

  • After step 3 you can determine whether a program will be found by PATH.

Quiz - Lesson PS.4

3DMake in Practice: Aliases and Profile Setup

PowerShell aliases and profile scripts make your 3DMake workflow much faster:

# Quick function to jump to your 3D projects folder
function 3dp { Set-Location ~/Documents/3d_projects }

# Quick function to run the full build-slice-print pipeline
function 3dprint { 3dm build slice print }

# Quick function to build and get an AI model description
function 3dinfo { 3dm build; 3dm info }

# Add these functions to your PowerShell profile so they load every session
notepad.exe $PROFILE
# (Paste the three functions above into the file, then save)

# Reload your profile without restarting PowerShell
. $PROFILE

# Now use them:
3dp            # jump to your 3D projects folder
3dprint        # run the full pipeline
3dinfo         # build and describe the model

Checkpoints

  • After step 3 you can determine whether a program will be found by PATH.

Quiz - Lesson PS.4

  1. How do you print an environment variable?
  2. What is the purpose of PATH?
  3. How do you check whether openscad is available?
  4. How do you create a temporary alias?
  5. Where would you make an alias permanent?
  6. True or False: Environment variables are case-sensitive on all platforms.
  7. Explain why having a program in your PATH is useful compared to always using its full file path.
  8. Write a command that would create an alias called slicer for the OpenSCAD executable.
  9. What file would you edit to make an alias persist across PowerShell sessions?
  10. Describe a practical benefit of using the $env:TEMP directory for temporary files in a 3D printing workflow.
  11. You have a custom script at C:\Scripts\backup_models.ps1 that you want to run from anywhere as backup-now. What steps would you take to make this work?
  12. Explain the difference between setting an environment variable in the current session vs. adding it to your profile for permanence.
  13. Design a profile strategy for managing multiple 3D printing projects, each with different tool paths and directories; show how to structure environment variables for each.
  14. If a program is not found by Get-Command, what are the possible reasons, and how would you troubleshoot?
  15. Describe how you would verify that your PowerShell profile is loading correctly and how to debug issues if aliases or environment variables don’t appear after restarting PowerShell.

Extension Problems

  1. Add a folder to PATH for a test program (describe steps; do not change system PATH without admin).
  2. Create a short profile snippet that sets two aliases and test re-opening PowerShell.
  3. Use Get-Command to list the path for several common programs.
  4. Explore $env:TEMP and create a file there.
  5. Save a copy of your current PATH to a text file and examine it in your editor.
  6. Create a PowerShell profile script that loads custom aliases and environment variables for your 3D printing workflow; test it in a new session.
  7. Build a “project profile” that sets environment variables for CAD, slicing, and print directories; switch between profiles for different projects.
  8. Write a script that audits your current environment variables and creates a summary report of what’s set and why.
  9. Design a custom alias system for common 3D printing commands; document the aliases and their purposes.
  10. Create a profile migration guide: document how to export and import your PowerShell profile across machines for consistent workflows.
  11. Implement a safe PATH modification script: create a utility that allows you to add/remove directories from PATH for the current session only; show how to make it permanent in your profile.
  12. Build a comprehensive profile framework with modules: create separate .ps1 files for aliases, environment variables, and functions; have your main profile load all of them dynamically.
  13. Develop an environment validation tool: write a script that checks whether all required programs (OpenSCAD, slicers, etc.) are accessible via PATH; report findings and suggest fixes.
  14. Create a project-switching alias system: design a function that changes all environment variables and aliases based on the current project; test switching between multiple projects.
  15. Build a profile troubleshooting guide: create a script that exports your current environment state (variables, aliases, PATH) to a timestamped file, allowing you to compare states before and after changes and identify what broke.

References

Helpful Resources


Lesson 5: Filling in the Gaps — Profiles and History


Estimated time: 30-45 minutes

Learning Objectives

  • Use history and abort commands (history, Ctrl+C)
  • Inspect and edit your PowerShell profile for persistent settings
  • Run programs by full path using the & operator
  • Handle common screen reader edge cases when using the terminal

Materials

  • PowerShell and an editor (Notepad/ VS Code)

Step-by-step Tasks

  1. Run several simple commands (e.g., pwd, ls -n, echo hi) then run history to view them.
  2. Use Invoke-History <n> to re-run a previous command (replace <n> with a history number).
  3. Practice aborting a long-running command with Ctrl + C (for example, ping 8.8.8.8).
  4. Open your profile: notepad.exe $PROFILE; if it doesn’t exist, create it: ni $PROFILE -Force.
  5. Add a persistent alias line to your profile (example: Set-Alias -Name preview -Value openscad), save, and reopen PowerShell to verify.

Checkpoints

  • After step 2 you can re-run a recent command by history number.
  • After step 5 your alias should persist across sessions.

Quiz - Lesson PS.5

  1. How do you view the command history?
  2. Which key combination aborts a running command?
  3. What does echo $PROFILE show?
  4. How does the & operator help run executables?
  5. What is one strategy if terminal output stops being announced by your screen reader?
  6. True or False: Using Ctrl+C permanently deletes any files created by the command you abort.
  7. Explain the difference between history and Get-History in PowerShell.
  8. If you place code in your profile but it doesn’t take effect after opening a new PowerShell window, what should you verify?
  9. Write a command that would run a program at the path C:\Program Files\OpenSCAD\openscad.exe directly.
  10. Describe a practical workflow scenario where having keyboard shortcuts (aliases) in your profile would save time.
  11. Explain how to re-run the 5th command from your history, and what would happen if that command had file operations (creates/deletes).
  12. Design a profile initialization strategy that separates utilities for different projects; explain how you would switch between them.
  13. Walk through a troubleshooting workflow: your screen reader stops announcing output after running a long command. What steps would you take to diagnose and resolve the issue?

Caution

Before any destructive operation — mass delete, bulk overwrite, or recursive removal — use history review (Get-History) and dry-run techniques (e.g., What-If) to verify the command is correct. A single mistaken path in a bulk delete can be unrecoverable.

  1. Create a safety checkpoint system: before any destructive operation (mass delete, overwrite), how would you use profile functions and history to verify the command is correct?
  2. Develop a comprehensive capstone scenario: integrate everything from Lessons 0–5 (navigation, file operations, piping, environment setup, history) to design an automated 3D printing project workflow with error handling and logging.

Extension Problems

  1. Add an alias and an environment variable change to your profile and document the behavior after reopening PowerShell.
  2. Create a short script that automates creating a project folder and an initial .scad file.
  3. Experiment with running OpenSCAD by full path using & and by placing it in PATH; compare results.
  4. Practice redirecting Get-Help output to a file and reading it in Notepad for screen reader clarity.
  5. Document three screen reader troubleshooting steps you used and when they helped.
  6. Build a comprehensive PowerShell profile that includes aliases, environment variables, and helper functions for your 3D printing workflow.
  7. Create a script that troubleshoots common PowerShell issues (module loading, permission errors, command not found); test at least three scenarios.
  8. Write a PowerShell function that coordinates multiple tasks: creates a project folder, starts OpenSCAD, and opens slicing software.
  9. Design a screen-reader accessibility guide for PowerShell: document commands, outputs, and accessible navigation patterns.
  10. Develop an advanced PowerShell workflow: implement error handling, logging, and confirmation prompts for risky operations.
  11. Implement a “undo” system using history: create a function that logs destructive commands (rm, mv, cp -Force) and allows you to review/rollback the last operation.
  12. Build a profile debugger: create a script that compares two PowerShell sessions’ environment states (variables, aliases, functions) to identify what loaded/failed to load.
  13. Develop a multi-project profile manager: design a system where you can switch entire environments (paths, aliases, variables) for different 3D printing projects by running a single command.
  14. Create a comprehensive accessibility analyzer: write a script that tests whether key PowerShell commands produce screen-reader-friendly output; document workarounds for commands that don’t.
  15. Design a complete capstone project: build an integrated automation suite that manages a 3D printing workflow (project setup, file organization, CAD/slicing tool automation, output logging, error recovery, and audit trails) with full error handling and documentation.

References

Helpful Resources


Lesson 6: Advanced Techniques — Scripts, Functions, and Professional Workflows


Duration: 4-4.5 hours (for screen reader users)
Prerequisites: Complete Lessons 0–5
Skill Level: Advanced intermediate

3DMake in Practice: Automating Your Print Workflow

Use PowerShell scripting to fully automate a 3DMake workflow across multiple projects:

# batch_print.ps1 - build and print every 3DMake project in a folder
param(
    [string]$ProjectsDir = "$HOME\Documents\3d_projects"
)

Get-ChildItem -Path $ProjectsDir -Directory | ForEach-Object {
    $project = $_.FullName
    $name = $_.Name
    Write-Host "Processing: $name"
    Set-Location $project

    # Build and slice; capture all output
    $output = & 3dm build slice 2>&1
    if ($LASTEXITCODE -eq 0) {
        Write-Host "  OK - sending to printer"
        & 3dm print
    } else {
        Write-Host "  FAILED - log saved to build_error.txt"
        $output | Out-File "build_error.txt"
        notepad.exe "build_error.txt"
    }
}

Write-Host "Batch complete."

Save as batch_print.ps1 and run with .\batch_print.ps1. This script uses loops, conditionals, and piping — all from this lesson.

This lesson extends PowerShell skills to professional-level workflows. You’ll learn to automate complex tasks, write reusable code, and integrate tools for 3D printing workflows.

Learning Objectives

By the end of this lesson, you will be able to:

  • Create and run PowerShell scripts (.ps1 files)
  • Write functions that accept parameters
  • Use loops to repeat tasks automatically
  • Automate batch processing of 3D models
  • Debug scripts when something goes wrong
  • Create professional workflows combining multiple tools

PowerShell Scripts Basics

What’s a Script?

A script is a file containing PowerShell commands that run in sequence. Instead of typing commands one by one, you put them in a file and run them all at once.

Why use scripts?

  • Repeatability: Run the same task 100 times identically
  • Documentation: Commands are written down for reference
  • Complexity: Combine many commands logically
  • Automation: Schedule scripts to run automatically

Creating Your First Script

Step 1: Open a text editor

notepad.exe my-first-script.ps1

Step 2: Type this script

# This is a comment - screen readers will read it
Write-Output "Script is running!"
pwd
ls -n
Write-Output "Script is done!"

Step 3: Save the file

  • In Notepad: Ctrl+S
  • Make sure filename ends in .ps1
  • Save in an easy-to-find location (like Documents)

Step 4: Run the script

.\my-first-script.ps1

What happens: PowerShell runs each command in sequence and shows output.

Important: Script Execution Policy

Caution

If you get an “execution policy” error when running a .ps1 script, PowerShell’s security is blocking unsigned scripts. Use -Scope Process to bypass it only for the current session — this is safer than changing the policy machine-wide.

On some Windows systems, you might get an error about “execution policy”. This is a security feature.

To fix it temporarily:

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process

Then try your script again:

.\my-first-script.ps1

Note for screen readers: Your screen reader will announce the error if there is one. Use Get-Help Get-ExecutionPolicy for more information.

Variables and Parameters

Using Variables

Variables store values you want to use later.

Example script:

$mypath = "C:\Users\YourName\Documents"
cd $mypath
Write-Output "I am now in:"
pwd
ls -n

Breaking it down:

  • $mypath = variable name (always starts with $)
  • = = assign the value after this
  • "C:\Users..." = the value (a path)
  • cd $mypath = use the variable (replace $mypath with its value)

Functions with Parameters

A function is reusable code that you can run with different inputs.

Example: A function that lists files in a folder

function ListFolder {
    param(
        [string]$path
    )
    Write-Output "Contents of: $path"
    cd $path
    ls -n
}
# Use the function:
ListFolder -path "C:\Users\YourName\Documents"
ListFolder -path "C:\Users\YourName\Downloads"

What’s happening:

  • function ListFolder = name of the function
  • param([string]$path) = the function accepts a parameter called $path
  • Inside the function, use $path like any variable
  • Call the function with -path "value"

Screen reader tip: When you call a function, PowerShell will announce the results just like any command.

Loops - Repeating Tasks

Loop Over Files

Imagine you have 10 SCAD files and want to print their contents. You could do it 10 times manually, or use a loop.

Example: Print every .scad file in a folder

$scadFiles = ls -n *.scad
foreach ($file in $scadFiles) {
    Write-Output "=== File: $file ==="
    cat $file
    Write-Output ""
}

What’s happening:

  • $scadFiles = ls -n *.scad = find all .scad files and store in variable
  • foreach ($file in $scadFiles) = for each file, do this:
    • Write-Output "=== File: $file ===" = announce which file
    • cat $file = show contents
    • Write-Output "" = blank line between files

Result: All files printed one after another, organized and readable.

Loop with a Counter

Example: Do something 5 times

for ($i = 1; $i -le 5; $i++) {
    Write-Output "This is iteration number $i"
    # Do something here
}

What’s happening:

  • for ($i = 1; $i -le 5; $i++) = loop from 1 to 5
  • $i = counter variable (starts at 1, increases each loop)
  • -le = “less than or equal to” (stop when $i > 5)
  • $i++ = add 1 to $i each time through

Real-World Example - Batch Processing SCAD Files

Scenario

You have 10 OpenSCAD (.scad) files in a folder. You want to:

  1. List them all
  2. Check how many there are
  3. For each one, verify it exists

The Script

# Batch Processing Script for SCAD Files
$scadFolder = "C:\Users\YourName\Documents\3D_Projects"
$scadFiles = ls $scadFolder -Filter *.scad -Name
Write-Output "Processing SCAD files in: $scadFolder"
Write-Output "Found $($scadFiles.Count) files"
Write-Output ""
foreach ($file in $scadFiles) {
    $fullPath = Join-Path -Path $scadFolder -ChildPath $file
    if (Test-Path -Path $fullPath) {
        Write-Output " Found: $file"
    } else {
        Write-Output " Missing: $file"
    }
}
Write-Output ""
Write-Output "Batch processing complete!"

Breaking it down:

  • $scadFolder = where to look
  • ls $scadFolder -Filter *.scad -Name = find .scad files, show names only
  • foreach = process each file
  • Join-Path = combine folder and filename into full path
  • Test-Path = check if file exists
  • if = do different things based on condition

Running the Script

  1. Save as batch-process.ps1
  2. Edit $scadFolder to match your real folder
  3. Run it:
    .\batch-process.ps1
    

Screen reader output:

Processing SCAD files in: C:\Users\YourName\Documents\3D_Projects
Found 10 files

 Found: model1.scad
 Found: model2.scad
 Found: model3.scad
[... more files ...]
Batch processing complete!

Error Handling

Try-Catch Blocks

What if something goes wrong? Use try-catch:

Example:

try {
    $file = "C:\nonexistent\path\file.txt"
    $content = cat $file
    Write-Output $content
} catch {
    Write-Output "Error: Could not read file"
    Write-Output "Details: $_"
}

What’s happening:

  • try = run these commands
  • If an error happens, PowerShell jumps to catch
  • catch = handle the error gracefully
  • $_ = the error message

Screen reader advantage: Errors are announced clearly instead of crashing silently.

Validating Input

Example: Make sure a folder exists before processing

function ProcessFolder {
    param([string]$folderPath)
    if (-not (Test-Path -Path $folderPath)) {
        Write-Output "Error: Folder does not exist: $folderPath"
        return
    }
    Write-Output "Processing folder: $folderPath"
    ls -n $folderPath
}
ProcessFolder -folderPath "C:\Users\YourName\Documents"

What’s happening:

  • Test-Path = check if folder exists
  • -not = if NOT true
  • return = exit the function early if error

Debugging Scripts

Common Errors and Solutions

Error 1: “Command not found”

Cause: Typo in command name

Fix: Check spelling

# Wrong:
writ-output "hello"
# Correct:
Write-Output "hello"

Error 2: “Variable is null”

Cause: Variable was never assigned

Fix: Make sure variable is set before using it

$myvar = "hello"  # Set first
Write-Output $myvar  # Then use

Error 3: “Cannot find path”

Cause: Wrong folder path

Fix: Verify path exists

# Check if path exists:
Test-Path -Path "C:\Users\YourName\Documents"
# If false, the path is wrong

Warning

“Access denied” means PowerShell doesn’t have permission to perform the operation. Always understand why you need administrator privileges before elevating — running everything as admin creates unnecessary security risk.

Error 4: “Access denied”

Cause: Don’t have permission

Fix: Run PowerShell as administrator

  • Right-click PowerShell -> Run as administrator

Debugging Technique: Trace Output

Add Write-Output statements to track what’s happening:

$path = "C:\Users\YourName\Documents"
Write-Output "Starting script. Path is: $path"
$files = ls -n $path
Write-Output "Found $($files.Count) files"
foreach ($file in $files) {
    Write-Output "Processing: $file"
    # Do something with $file
    Write-Output "Done with: $file"
}
Write-Output "Script complete"

Your screen reader will announce each step, so you know where errors happen.

Creating Professional Workflows

Example 1: Automated Project Setup

Scenario: You start a new 3D printing project regularly. Instead of creating folders manually:

function SetupNewProject {
    param([string]$projectName)
    $baseFolder = "C:\Users\YourName\Documents\3D_Projects"
    $projectFolder = Join-Path -Path $baseFolder -ChildPath $projectName
    # Create folder structure
    mkdir $projectFolder -Force
    mkdir "$projectFolder\designs" -Force
    mkdir "$projectFolder\output" -Force
    mkdir "$projectFolder\notes" -Force
    # Create a README
    $readmeContent = @"
# $projectName
Created: $(Get-Date)
## Designs
All .scad files go here.
## Output
STL and other exports go here.
## Notes
Project notes and observations.
"@
    $readmeContent | Out-File -FilePath "$projectFolder\README.txt" -Encoding utf8
    Write-Output "Project setup complete: $projectFolder"
}
# Use it:
SetupNewProject -projectName "MyKeychain"
SetupNewProject -projectName "PhoneStand"

What it does:

  • Creates folder structure for a new project
  • Sets up subfolders for designs, output, notes
  • Creates a README file automatically

Example 2: Batch File Verification

Scenario: Before processing, verify all required files exist:

function VerifyProjectFiles {
    param([string]$projectFolder)
    $requiredFiles = @(
        "README.txt",
        "designs",
        "output",
        "notes"
    )
    $allGood = $true
    foreach ($item in $requiredFiles) {
        $path = Join-Path -Path $projectFolder -ChildPath $item
        if (Test-Path -Path $path) {
            Write-Output " Found: $item"
        } else {
            Write-Output " Missing: $item"
            $allGood = $false
        }
    }
    if ($allGood) {
        Write-Output "All checks passed!"
        return $true
    } else {
        Write-Output "Some files are missing!"
        return $false
    }
}
# Use it:
$verified = VerifyProjectFiles -projectFolder "C:\Users\YourName\Documents\3D_Projects\MyKeychain"
if ($verified) {
    Write-Output "Safe to proceed with processing"
}

Screen Reader Tips for Scripts

Making Script Output Readable

Problem: Script runs but output scrolls too fast or is hard to follow

Solution 1: Save to file

.\my-script.ps1 > output.txt
notepad.exe output.txt

Solution 2: Use Write-Output with clear sections

Write-Output "========== STARTING =========="
Write-Output ""
# ... script ...
Write-Output ""
Write-Output "========== COMPLETE =========="

Solution 3: Pause between major sections

Write-Output "Pausing... Press Enter to continue"
Read-Host

Your screen reader will announce the pause, give you time to read output.

Announcing Progress

For long-running scripts:

$files = ls -n *.scad
$count = 0
foreach ($file in $files) {
    $count++
    Write-Output "Processing $count of $($files.Count): $file"
    # Do something with $file
}
Write-Output "All $count files processed!"

Practice Exercises

Exercise 1: Your First Script

Goal: Create and run a simple script

Steps:

  1. Create file: notepad.exe hello.ps1
  2. Type:
    Write-Output "Hello from my first PowerShell script!"
    pwd
    ls -n
    
  3. Save and run: .\hello.ps1

Checkpoint: You should see output for each command.

Exercise 2: Script with a Variable

Goal: Use a variable to make the script flexible

Steps:

  1. Create file: notepad.exe smart-listing.ps1
  2. Type:
    $targetFolder = "C:\Users\YourName\Documents"
    Write-Output "Listing contents of: $targetFolder"
    ls -n $targetFolder
    
  3. Edit $targetFolder to a real folder on your computer
  4. Run: .\smart-listing.ps1

Checkpoint: You should see listing of that specific folder.

Exercise 3: Function

Goal: Create a reusable function

Steps:

  1. Create file: notepad.exe navigate.ps1
  2. Type:
    function GoTo {
        param([string]$path)
        if (Test-Path -Path $path) {
            cd $path
            Write-Output "Now in: $(pwd)"
            Write-Output "Contents:"
            ls -n
        } else {
            Write-Output "Path does not exist: $path"
        }
    }
    # Test the function:
    GoTo -path "C:\Users\YourName\Documents"
    GoTo -path "C:\Users\YourName\Downloads"
    
  3. Run: .\navigate.ps1

Checkpoint: Both commands should work, showing contents of each folder.

Exercise 4: Loop

Goal: Use a loop to repeat an action

Steps:

  1. Create file: notepad.exe repeat.ps1
  2. Type:
    Write-Output "Demonstrating a loop:"
    for ($i = 1; $i -le 5; $i++) {
        Write-Output "Iteration $i: Hello!"
    }
    Write-Output "Loop complete!"
    
  3. Run: .\repeat.ps1

Checkpoint: Should print “Iteration 1” through “Iteration 5”.

Exercise 5: Real-World Script

Goal: Create a useful script for a real task

Steps:

  1. Create a folder: mkdir C:\Users\YourName\Documents\TestFiles
  2. Create some test files:
    echo "test" > C:\Users\YourName\Documents\TestFiles\file1.txt
    echo "test" > C:\Users\YourName\Documents\TestFiles\file2.txt
    echo "test" > C:\Users\YourName\Documents\TestFiles\file3.txt
    
  3. Create script: notepad.exe report.ps1
  4. Type:
    $folder = "C:\Users\YourName\Documents\TestFiles"
    $files = ls -n $folder
    Write-Output "=== FILE REPORT ==="
    Write-Output "Folder: $folder"
    Write-Output "Total files: $($files.Count)"
    Write-Output ""
    Write-Output "Files:"
    foreach ($file in $files) {
        Write-Output "  - $file"
    }
    Write-Output ""
    Write-Output "=== END REPORT ==="
    
  5. Run: .\report.ps1

Checkpoint: Should show report of all files in the test folder.

Quiz — Lesson 6

  1. What is a PowerShell script?
  2. What file extension do PowerShell scripts use?
  3. What is a variable and how do you create one?
  4. What is a function and why would you use one?
  5. How do you run a script?
  6. What is a loop and what does foreach do?
  7. What does Test-Path do?
  8. How do you handle errors in a script?
  9. When would you use Try-Catch?
  10. What technique makes script output readable for screen readers?

Extension Problems

  1. Auto-Backup Script: Create a script that copies all files from one folder to another, announcing progress
  2. File Counter: Write a function that counts files by extension (.txt, .scad, .stl, etc.)
  3. Folder Cleaner: Script that deletes files older than 30 days (with user confirmation)
  4. Project Template: Function that creates a complete project folder structure with all needed files
  5. Batch Rename: Script that renames all files in a folder according to a pattern
  6. Log Generator: Create a script that records what it does to a log file for later review
  7. Scheduled Task: Set up a script to run automatically every day at a specific time
  8. File Verifier: Check that all SCAD files in a folder have corresponding STL exports
  9. Report Generator: Create a summary report of all projects in a folder
  10. Error Tracker: Script that lists all commands that had errors in your recent history

Important Notes

  • Always test scripts on small sets of files first before running them on important data
  • Save your work regularly - use version control if possible
  • Test error handling - make sure errors don’t crash silently
  • Document your scripts - use comments so you remember what each part does
  • Backup before batch operations - if something goes wrong, you have the original

References

Next Steps: After mastering this lesson, explore PowerShell modules, remoting, and 3D printing integration in the main curriculum.


Unit Exam — Comprehensive Assessment


Estimated time: 60-90 minutes

Key Learning Outcomes Assessed

By completing this unit test, you will demonstrate:

  1. Understanding of file system navigation and path concepts
  2. Proficiency with file and folder manipulation commands
  3. Ability to redirect and pipe command output
  4. Knowledge of environment variables and aliases
  5. Screen-reader accessibility best practices in terminal environments
  6. Problem-solving and command chaining skills

Target Audience:

Users who have completed Lessons 0–5 and need to demonstrate mastery of PowerShell fundamentals.

Instructions:

Complete all sections below. For multiple choice, select the best answer. For short answers, write one to two sentences. For hands-on tasks, capture evidence (screenshots or output files) and submit alongside your answers.

Part A: Multiple Choice Questions (20 questions)

Select the best answer for each question. Each question is worth 1 point.

  1. What is the primary purpose of the PATH environment variable?

    • A) Store your home directory location
    • B) Tell the shell where to find executable programs
    • C) Configure the visual appearance of the terminal
    • D) Store the current working directory name
  2. Which command prints your current working directory?

    • A) ls -n
    • B) cd
    • C) pwd
    • D) whoami
  3. What does the ~ symbol represent in PowerShell paths?

    • A) The root directory
    • B) The current directory
    • C) The parent directory
    • D) The home directory
  4. How do you list only file names (not full details) in a way that is screen-reader friendly?

    • A) ls
    • B) ls -n
    • C) ls -l
    • D) cat -n
  5. Which command creates a new empty file?

    • A) mkdir filename
    • B) ni filename
    • C) touch filename
    • D) echo filename

Important

> overwrites a file completely — all previous content is lost. >> appends to the end of a file, preserving existing content. Using > when you meant >> will permanently destroy the file’s previous contents.

  1. What is the difference between > and >>?

    • A) > redirects to file, >> displays on screen
    • B) > overwrites a file, >> appends to a file
    • C) They do the same thing
    • D) > is for text, >> is for binary
  2. What does the pipe operator | do?

    • A) Creates a folder
    • B) Sends the output of one command to the input of another
    • C) Deletes files matching a pattern
    • D) Lists all processes
  3. Which command copies a file?

    • A) mv
    • B) rm
    • C) cp
    • D) cd
  4. How do you rename a file from oldname.txt to newname.txt?

    • A) cp oldname.txt newname.txt
    • B) mv oldname.txt newname.txt
    • C) rename oldname.txt newname.txt
    • D) rn oldname.txt newname.txt
  5. What is the purpose of Select-String?

    • A) Select files in a directory
    • B) Search for text patterns within a file
    • C) Select a string to copy to clipboard
    • D) Select which shell to use
  6. Which key combination allows you to autocomplete a path in PowerShell?

    • A) Ctrl + A
    • B) Ctrl + E
    • C) Tab
    • D) Space
  7. How do you copy text to the Windows clipboard from PowerShell?

    • A) cat filename > clipboard
    • B) cat filename | clip
    • C) copy filename
    • D) cat filename | paste
  8. What does Get-Command openscad do?

    • A) Opens the OpenSCAD application
    • B) Gets help about the OpenSCAD command
    • C) Locates the full path of the openscad executable
    • D) Lists all available commands
  9. Which wildcard matches any single character?

    • A) *
    • B) ?
    • C) %
    • D) #
  10. What is the purpose of the & call operator?

    • A) Run a script or executable by full path
    • B) Execute all commands in parallel
    • C) Combine multiple commands
    • D) Create an alias
  11. How do you create a temporary alias for a command?

    • A) alias preview='openscad'
    • B) Set-Alias -Name preview -Value openscad
    • C) New-Alias preview openscad
    • D) Alias preview = openscad
  12. Where is your PowerShell profile typically stored?

    • A) C:\Program Files\PowerShell\profile.ps1
    • B) The location returned by echo $PROFILE
    • C) ~/PowerShell/profile.ps1
    • D) ~/.bashrc
  13. How do you abort a long-running command in PowerShell?

    • A) Press Escape
    • B) Press Ctrl + X
    • C) Press Ctrl + C
    • D) Press Alt + F4
  14. What command shows the history of previously run commands?

    • A) history
    • B) Get-History
    • C) Show-History
    • D) Both A and B
  15. How do you permanently set an alias so it persists across PowerShell sessions?

    • A) Use Set-Alias in the terminal every time
    • B) Add the Set-Alias line to your PowerShell profile
    • C) Use the Windows Control Panel
    • D) Aliases cannot be made permanent

Part B: Short Answer Questions (10 questions)

Answer each question in one to two sentences. Each question is worth 2 points.

  1. Explain the difference between absolute and relative paths. Give one example of each.

  2. Why is ls -n preferred over ls for screen reader users? Describe what flag you would use to list only files.

  3. What is the purpose of redirecting output to a file, and give an example of when you would use > instead of >>?

Warning

rm -r ~/Documents/my_folder permanently deletes the folder and everything inside it — all files, all subdirectories — with no confirmation and no undo. Always verify the path with ls -1 first and consider making a backup with cp -r before running recursive deletions.

  1. Describe what would happen if you ran rm -r ~/Documents/my_folder and why this command should be used carefully.

  2. How would you search for all files with a .scad extension in your current directory? Write the command.

  3. Explain what happens when you pipe the output of ls -n into clip. What would you do next?

  4. What is an environment variable, and give one example of how you might use it in PowerShell.

  5. If a program is not in your PATH, what two methods could you use to run it from PowerShell?

  6. Describe how you would open a file in Notepad and also add a line to it from PowerShell.

  7. What is one strategy you would use if your screen reader stops announcing terminal output while using PowerShell?

Part C: Hands-On Tasks (10 tasks)

Complete each task and capture evidence (screenshots, output files, or command transcripts). Each task is worth 3 points.

Tasks 1-5: File System and Navigation

  1. Create a folder structure ~/Documents/PowerShell_Assessment/Projects using a single command. Capture the ls -n output showing the creation.

  2. Create five files named project_1.scad, project_2.scad, project_3.txt, notes_1.txt, and notes_2.txt inside the Projects folder. Use wildcards to list only .scad files, then capture the output.

  3. Copy the entire Projects folder to Projects_Backup using cp -r. Capture the ls -n output showing both folders exist.

  4. Move (rename) project_1.scad to project_1_final.scad. Capture the ls -n output showing the renamed file.

  5. Delete notes_1.txt and notes_2.txt using a single rm command with wildcards. Capture the final ls -n output.

Tasks 6-10: Advanced Operations and Scripting

  1. Create a file called my_data.txt with at least four lines using echo and >>. Then read it with cat my_data.txt and capture the output.

  2. Use Select-String to search for a keyword (e.g., “project”) in my_data.txt and pipe the results to clip. Paste the results into Notepad and capture a screenshot.

  3. List all files in the Projects folder and redirect the output to projects_list.txt. Open it in Notepad and capture a screenshot of the file.

  4. Create a temporary alias called myls that runs ls -n, test it, and capture the output. Then explain what would be required to make it permanent.

  5. Run Get-Help Get-ChildItem and redirect the output to help_output.txt. Open the file in Notepad and capture a screenshot showing at least the first page of help content.

Grading Rubric

SectionQuestionsPoints EachTotal
Multiple Choice20120
Short Answer10220
Hands-On Tasks10330
Total40-70

Passing Score: 49 points (70%)

Helpful Resources for Review

Submission Checklist

  • All 20 multiple choice questions answered
  • All 10 short answer questions answered (1-2 sentences each)
  • All 10 hands-on tasks completed with evidence captured
  • Files/screenshots organized and labeled clearly
  • Submission includes this checklist

Part 2 — Windows Command Prompt (CMD)


Last Updated: February 2026
Total Duration: 30–45 hours of instruction and practice (for screen reader users)
Target Users: Anyone using a screen reader — NVDA, JAWS, Windows Narrator, and Dolphin SuperNova are all covered throughout this curriculum.
Alternate to: PowerShell curriculum (same concepts, CMD syntax)

This single file contains the complete CMD Foundation curriculum in reading order. All lessons, quizzes, extension problems, and the unit exam are included. No additional files are needed.


Table of Contents

SectionTitleEstimated Time
Screen Reader Accessibility GuideNVDA, JAWS, Narrator, and SuperNova reference for CMD1.5 hours
Lesson Pre: Your First TerminalOpening CMD, first commands, basic navigation1.5–2 hours
Lesson 0: Getting StartedPaths, shortcuts, tab completion1.5 hours
Lesson 1: NavigationMoving around the file system confidently2–2.5 hours
Lesson 2: File and Folder ManipulationCreate, copy, move, delete files and folders2.5–3 hours
Lesson 3: Input, Output, and PipingRedirect output, chain commands with pipes2.5–3 hours
Lesson 4: Environment Variables and AliasesAutomate settings, create doskey shortcuts2–2.5 hours
Lesson 5: Filling in the GapsAutorun scripts, history, debugging2–2.5 hours
Lesson 6: Advanced TechniquesBatch scripts, subroutines, loops, professional workflows4–4.5 hours
Unit ExamComprehensive assessment — Lessons 0 through 660–90 minutes

Total: approximately 30–45 hours including practice exercises


How to Use This File

If you have never used a terminal before: read from the top in order. Do not skip lessons — each builds on the one before it.

If you have used a terminal but not with a screen reader: start with the Accessibility Guide, skim Lesson Pre, then continue from Lesson 0.

If you are experienced with both: jump directly to the lesson you need. Use the quiz at the end of each lesson to self-test before moving on.

Reference while working: the Accessibility Guide contains material you will return to throughout the curriculum. Keep a copy open or bookmark that section.

PowerShell users: this curriculum covers the same concepts as the PowerShell curriculum but uses CMD syntax. The two curricula are interchangeable as learning paths — choose one and stay consistent.


Curriculum Rules (Read These First)

Important

Rule 1 — Always know where you are. Start every session with cd (no arguments) to print your current location. If you don’t know your path, you will get lost and may operate on the wrong files.

Rule 1 — Always know where you are.
Every session, first thing: cd (with no arguments). If you do not know your path, you will get lost.

Warning

Files deleted from CMD do not go to the Recycle Bin. They are permanently gone immediately. Always run dir /B to confirm exactly what you are about to delete before running del or rmdir /S.

Rule 2 — Check before you delete.
Before any del or rmdir command: dir /B to confirm exactly what you are about to remove. Deleted files do not go to the Recycle Bin from CMD.

Tip

Always use dir /B — never bare dir. The /B (bare) flag outputs one name per line, which screen readers can follow reliably. Bare dir outputs multi-column details that can be difficult to navigate audibly.

Rule 3 — Use dir /B for listings.
Always dir /B — never bare dir. The /B flag gives one name per line, which all screen readers can follow reliably.

Tip

When terminal output is confusing or overwhelming, redirect it to a file: command > output.txt, then open it with notepad.exe output.txt. This is clearer than reading raw terminal output and works with all four screen readers.

Rule 4 — When output is confusing, redirect to a file.
command > output.txt then notepad.exe output.txt. This works with all four screen readers.

Rule 5 — Save everything you create.
Keep all practice files in a dedicated learning folder: mkdir %USERPROFILE%\CMD_Learning



Screen Reader Accessibility Guide


Target Users: NVDA, JAWS, and other screen reader users
Last Updated: 2026

This guide supports the CMD Foundation curriculum and helps screen reader users navigate and work efficiently with the Windows Command Prompt.

Table of Contents

  1. Getting Started with Screen Readers
  2. NVDA-Specific Tips
  3. JAWS-Specific Tips
  4. General Terminal Accessibility
  5. Working with Long Output
  6. Keyboard Shortcuts Reference
  7. Troubleshooting

Getting Started with Screen Readers

Which Screen Reader Should I Use?

Both NVDA and JAWS work with CMD; NVDA is free and often easiest to start with. JAWS provides advanced features for power users. Dolphin SuperNova and Windows Narrator are also options:

  • Dolphin SuperNova: commercial speech, braille, and magnification (use vendor docs for key mappings).
  • Windows Narrator: built into Windows for quick, no-install access.

Before You Start

  1. Start your screen reader before opening CMD.
  2. Open Command Prompt and listen for the window title and prompt.
  3. If silent, press Alt+Tab to find the window.

What is CMD?

CMD (Command Prompt) is the classic Windows shell. Common commands include dir, type, and more. Paths use backslashes (e.g., C:\Users\You).

NVDA-Specific Tips

NVDA is available from https://www.nvaccess.org/

Dolphin SuperNova

Dolphin SuperNova: https://yourdolphin.com/supernova/ — commercial screen reader and magnifier; check institutional licensing.

Windows Narrator

Windows Narrator: https://support.microsoft.com/narrator — built-in, simpler command set; useful when third-party readers are unavailable.

Key Commands for CMD

CommandWhat It Does
NVDA+HomeRead the current line (your command or output)
NVDA+Down ArrowRead from cursor to end of screen
NVDA+Up ArrowRead from top to cursor
NVDA+Page DownRead next page
NVDA+Page UpRead previous page
NVDA+F7Open the Review Mode viewer (can scroll through text)

Example: Reading Long Output

If dir produces many lines, redirect to a file and open it in Notepad:

dir /b > list.txt
notepad list.txt

dir /b shows one item per line (screen reader friendly).

JAWS-Specific Tips

JAWS is available from https://www.freedomscientific.com/

Key Commands for CMD

CommandWhat It Does
Insert+Down ArrowRead line by line downward
Insert+Up ArrowRead line by line upward
Insert+Page DownRead next page of text
Insert+Page UpRead previous page of text

Example: Reading Long Output

  1. Redirect: dir /b > list.txt
  2. Open Notepad: notepad list.txt
  3. Use Insert+Ctrl+Down to read full contents.

General Terminal Accessibility

Understanding the CMD Layout

The Command Prompt window shows a title bar, a content area, and the prompt (e.g., C:\Users\YourName>).

The CMD Prompt

Example:

C:\Users\YourName>
  1. Screen reader announces the title
  2. Then it announces the prompt line
  3. Anything above prompt is prior output

Working with Long Output

Solution 1: Redirect to a File

dir /b > list.txt
notepad list.txt

Solution 2: Use Pagination

type largefile.txt | more

Use Space for next page and Q to quit.

Solution 3: Filter Output

dir /b | findstr /R "\.scad$"

Solution 4: Count Before Displaying

dir /b | find /v "" /c

Keyboard Shortcuts Reference

KeyAction
Up ArrowShow previous command
Down ArrowShow next command
TabAuto-complete file/folder names
HomeJump to start of line
EndJump to end of line
Ctrl+CStop command
EnterRun command

Troubleshooting

Problem: “I Can’t Hear the Output”

  1. Redirect to file and open in Notepad.
  2. Use End to jump to the end of text.

Problem: “Tab Completion Isn’t Working”

  1. Type at least one character before Tab.

Problem: “Command Not Found”

  1. Use where programname to find installed programs.

Pro Tips

  1. Use dir /b for one-per-line listings.
  2. Create a personal notes file and open it in Notepad for quick reference.
  1. cd to the project folder
  2. dir /b to list files
  3. Redirect large output to files and open in Notepad

Additional Resources


Lesson Pre: Your First Terminal — Screen Reader Navigation Fundamentals


Duration: 1.5-2 hours (for screen reader users)
Prerequisites: None — this is the starting point
Accessibility Note: This lesson is designed specifically for screen reader users. Tips are provided for NVDA, JAWS, Windows Narrator, and Dolphin SuperNova.


What is a Terminal?

A terminal (also called command line or Command Prompt) is a text-based interface where you type commands instead of clicking buttons. Think of it like sending written instructions to your computer instead of pointing and clicking.

Why learn this?

  • Faster and more precise work, especially for 3D printing scripts and automation.
  • Essential for using tools like OpenSCAD.
  • Accessibility: command-line tools work reliably with screen readers — output is plain text.
  • Simple automation without complex graphical interfaces.

Opening Command Prompt for the First Time

3DMake: Your First Real-World Goal

3DMake (github.com/tdeck/3dmake) is a free, accessibility-first command-line tool for designing and 3D-printing models entirely from the terminal — no mouse required. Every CMD skill in this curriculum directly supports a real 3DMake workflow.

Here is the end goal — one command that builds your OpenSCAD model, slices it, and sends it to the printer:

REM Navigate to your project folder
cd %USERPROFILE%\Documents\3d_projects\my_cube

REM Build, slice, and print in a single command
3dm build slice print

Keep this goal in mind as you work through each lesson.


Opening Command Prompt for the First Time

Method 1: Search (Easiest)

  1. Press the Windows key alone.
  2. Type: cmd
  3. You will hear search results appear.
  4. Press Enter to open the first result (Command Prompt).

Method 2: Using the Run Dialog

  1. Press Windows key + R (opens the Run dialog).
  2. Type: cmd
  3. Press Enter.

Method 3: From the Start Menu

  1. Press the Windows key.
  2. Navigate to Windows System or Windows Tools (depending on your Windows version).
  3. Open Command Prompt.

First Connection: Understanding the Prompt

When Command Prompt opens, your screen reader will announce the window title and then the prompt. The prompt is where you type commands.

What you will hear:

C:\Users\YourName>

What this means:

  • C:\Users\YourName = Your current location (the path).
  • > = The prompt is ready for input.

Your cursor is right after the >. This is where you type.


Your First Commands (Screen Reader Edition)

Command 1: “Where Am I?” — cd

Running cd with no arguments shows your current directory.

Type this and press Enter:

cd

What you will hear: Your screen reader announces the current path, for example:

C:\Users\YourName

Understanding paths:

  • A path shows your location in the file system, like a mailing address.
  • Windows paths use backslashes: C:\Users\YourName\Documents
  • Think of it as nested folders: C:\ (the main drive) > Users > YourName > Documents

Command 2: “What’s Here?” — dir

Type this and press Enter:

dir /B

What you will hear: Your screen reader announces folder and file names, one per line. The /B flag gives a clean “bare” listing — names only, no dates or sizes — which is much easier to follow with a screen reader.

If you want more detail (sizes, dates), run dir without /B. But for navigation, dir /B is preferred.

Command 3: “Go There” — cd Documents

Type this and press Enter:

cd Documents

What you will hear: The prompt changes to show your new location:

C:\Users\YourName\Documents>

Practice navigation:

  1. Run cd to confirm you are in Documents.
  2. Run dir /B to see what is there.
  3. Go back up: cd .. (the .. means “go up one level”).
  4. Run cd again to confirm.
  5. Return to Documents: cd Documents

Reading Screen Reader Output (Critical Skills)

Dealing with Long Lists

When you run dir in a folder with many files, the list may be very long. Here is how to manage it:

Solution 1: Save to a File

dir /B > list.txt
notepad.exe list.txt

This saves the listing to a file and opens it in Notepad, where you can read it calmly with your screen reader.

Solution 2: Use Pause

dir /B | more

Shows output one page at a time. Press Space to go to the next page, Q to quit. Note: some screen readers read more output less reliably than a saved file — if this is difficult, use Solution 1.

Tab Completion

Tab completion is one of the most powerful screen reader techniques in the terminal.

How it works:

  1. Type the first few letters of a folder or file name.
  2. Press Tab.
  3. Command Prompt automatically completes the rest.

Example:

  1. You are at C:\Users\YourName>
  2. Type: cd Doc
  3. Press Tab
  4. Command Prompt completes it to: cd Documents
  5. Press Enter to navigate there.

With a screen reader, when you press Tab the screen reader announces the completed command — much faster and more accurate than typing the whole thing.


Creating and Viewing Files

Create a Simple File

echo Hello, Command Prompt! > hello.txt
  • echo outputs text.
  • > redirects it to a file called hello.txt.

Read the File Back

type hello.txt

Your screen reader announces the file contents.

Open and Edit the File

notepad.exe hello.txt

Opens the file in Notepad for comfortable editing with your screen reader.


Essential Keyboard Shortcuts

Key CombinationWhat It Does
Up ArrowShows your previous command (press again for earlier commands)
Down ArrowShows a more recent command in history
TabAuto-completes folder and file names
Ctrl+CStops a running command
clsClears the screen (type this and press Enter)
EnterRuns the command you have typed
HomeMoves cursor to start of command line
EndMoves cursor to end of command line

Screen Reader-Specific Tips

NVDA Users

NVDA is available free from https://www.nvaccess.org/

  1. After running a command, press NVDA+Home (Insert+Home or CapsLock+Home) to read the current line.
  2. To read all output, press NVDA+Down Arrow to read from the cursor to the end of the screen.
  3. To browse previous output, use the NVDA review cursor: press Numpad 8/2 (desktop) or the equivalent laptop keys to move up and down through lines.
  4. If output scrolled past, redirect to a file: command > output.txt, then notepad.exe output.txt.
  5. To open NVDA settings: press NVDA+N (opens NVDA menu), then go to Preferences.

NVDA key note: The NVDA modifier key is Insert by default on desktops. On laptops it is often CapsLock. Check your NVDA settings if these shortcuts do not work as described.

JAWS Users

JAWS is available from https://www.freedomscientific.com/products/software/jaws/

  1. After running a command, press Insert+Up Arrow to re-read the current line.
  2. To read all output, press Insert+Ctrl+Down to read to the end of the screen.
  3. To move through output line by line, press Insert+Down Arrow repeatedly.
  4. If output is too long, redirect to a file: command > output.txt, then notepad.exe output.txt.
  5. JAWS demo mode reminder: If you are using JAWS without a license, sessions are limited to approximately 40 minutes. Save your work and restart the session if JAWS stops responding.

JAWS key note: The JAWS modifier key is Insert by default. On some laptops it can be set to CapsLock in JAWS Settings Center.

Windows Narrator Users

Windows Narrator is built into Windows 10 and Windows 11. Enable it with Windows+Ctrl+Enter.

  1. After running a command, press Narrator+D (CapsLock+D or Insert+D) to read the current line.
  2. To read all output from here, press Narrator+R to read from the cursor position.
  3. To move through output, use Narrator+Up/Down Arrow in scan mode (press Narrator+Space to toggle scan mode on).
  4. For long outputs, always redirect to a file: command > output.txt, then notepad.exe output.txt. Notepad is more comfortable for Narrator users than reading directly from the terminal.
  5. Narrator settings: Windows key > Settings > Accessibility > Narrator.

Narrator key note: The Narrator modifier key is CapsLock or Insert. You can change it in Settings > Accessibility > Narrator > Keyboard shortcuts.

Dolphin SuperNova Users

Dolphin SuperNova is available from https://yourdolphin.com/supernova/

  1. After running a command, press CapsLock+L to read the current line.
  2. To read all output, press CapsLock+Numpad Plus (say all from current position).
  3. To move through output, press CapsLock+Numpad 8 (up) and CapsLock+Numpad 2 (down) to move line by line through the review buffer.
  4. For long outputs, redirect to a file: command > output.txt, then notepad.exe output.txt.
  5. SuperNova settings: press CapsLock+SpaceBar to open the SuperNova Control Panel.

Dolphin key note: The SuperNova modifier key is CapsLock by default. This can be changed in the SuperNova Control Panel > Keyboard.


Common Issue: “I Can’t Hear the Output”

This happens to everyone starting out. Here are the solutions:

  1. Make sure your screen reader was running before you opened Command Prompt. If not, close Command Prompt, confirm your screen reader is running, then reopen it.
  2. Press End to make sure your cursor is at the prompt.
  3. Redirect to a file: command > output.txt, then notepad.exe output.txt. This always works with all screen readers.
  4. Use the screen reader’s review commands listed above to scan back through previous output.

Practice Exercises

Complete these in order. Take your time.

Exercise 1: Basic Navigation

  1. Open Command Prompt.
  2. Run cd and note your location.
  3. Run dir /B and listen to the listing.
  4. Type cd Documents and press Enter.
  5. Run cd to confirm your new location.
  6. Run dir /B in this new location.

Goal: You know where you are and what is around you.

Exercise 2: Using Tab Completion

  1. In your home directory, type cd D (just those two characters).
  2. Press Tab.
  3. Command Prompt should auto-complete to a folder starting with D.
  4. Repeat with other folder names.
  5. Try cd Down and Tab to Downloads.

Goal: Tab completion feels natural.

Exercise 3: Creating and Viewing Files

  1. Create a file: echo Test content > test.txt
  2. View it: type test.txt
  3. Create another: echo Line 2 > another.txt
  4. List both: dir /B *.txt

Goal: You understand create, view, and list operations.

Exercise 4: Going Up Levels

  1. Navigate into several folders: cd Documents, then cd folder1, etc.
  2. From inside, run cd .. multiple times to come back up.
  3. After each cd .., run cd to confirm your location.

Goal: You are comfortable with relative navigation using ..

Exercise 5: Redirecting Output

  1. Create a listing: dir /B > directorylist.txt
  2. Open it: notepad.exe directorylist.txt
  3. Read it with your screen reader.
  4. Close Notepad.

Goal: You can save long outputs to files for easier reading.


Checkpoint Questions

After this lesson, you should be able to answer all ten with confidence:

  1. What does cd do with no arguments?
  2. What does dir /B do?
  3. Why do we use /B with dir?
  4. What is your current path right now?
  5. How do you navigate to a new folder?
  6. How do you go up one level?
  7. What is the Tab key for?
  8. What does echo text > file.txt do?
  9. How do you read a file back in the terminal?
  10. How do you stop a command that is running?

Answer all 10 before moving to Command Line Lesson 0.


Common Questions

Q: Should I use Command Prompt or PowerShell?
A: Command Prompt is simpler and a good starting point. PowerShell is more powerful. Both work well with all four screen readers covered in this curriculum. Start with whichever your curriculum pathway specifies.

Q: Why is my screen reader not reading the output?
A: This is common. Use command > file.txt to save output to a file, then open it with notepad.exe file.txt for reliable reading.

Q: What if I type something wrong?
A: Press Enter and you will see an error message. Type the correct command on the next line. No harm done.

Q: How do I get help with a command?
A: Type help command-name (for example, help cd). Or type command /? for built-in help (for example, dir /?).


Next Steps

Once comfortable with these basics, move to Command Line Lesson 0: Getting Started for deeper path understanding, then continue through Command Line Lesson 1 to Command Line Lesson 5 for full terminal mastery.


Troubleshooting

IssueSolution
Command Prompt won’t openPress Windows+R, type cmd, press Enter
Cannot hear the outputRedirect to a file: command > output.txt, then notepad.exe output.txt
Tab completion not workingType at least one character before pressing Tab
Command not foundCheck spelling; try help for a list of available commands
Stuck in a commandPress Ctrl+C to stop it
JAWS stops working mid-sessionIf using JAWS demo: restart computer, demo sessions last ~40 minutes

Resources


Lesson 0: Getting Started — Layout, Paths, and the Shell


Estimated time: 20-30 minutes

Learning Objectives

  • Launch Command Prompt and locate the prompt
  • Understand path notation and shortcuts (C:\, .., .)
  • Use tab completion to navigate quickly

Materials

  • Computer with Windows
  • Editor (Notepad/VS Code)

Step-by-step Tasks

  1. Open Command Prompt and note the prompt (it includes the current path).
  2. Run cd and say or note the printed path.
  3. Use dir /B to list names in your home directory.
  4. Practice cd Documents, cd .. and cd \ until comfortable.
  5. Try tab-completion: type cd D and press Tab.

Checkpoints

  • Confirm you can state your current path and move to Documents.

3DMake Quick-Start: Your First Real Project

You now know enough CMD to set up a real 3DMake project. Do this now — it is the fastest path to a printed object.

Step 1 — Download and run the 3DMake setup wizard:

REM Go to your Downloads folder (where you extracted 3dmake_windows.zip)
cd %USERPROFILE%\Downloads\3dmake

REM Run the guided setup (answer the questions about your printer)
3dm setup

Step 2 — Create your first project:

REM Create a folder for all your 3D projects
mkdir %USERPROFILE%\Documents\3d_projects

REM Create your first project folder and initialize it
mkdir %USERPROFILE%\Documents\3d_projects\my_cube
cd %USERPROFILE%\Documents\3d_projects\my_cube
3dm new

Step 3 — Confirm the project structure:

REM You should see three items: src, build, and 3dmake.toml
dir /B

You just used mkdir, cd, and dir /B on a real project. You are ready to print.

Checkpoints

  • Confirm you can state your current path and move to Documents.

Quiz - Lesson CMD.0

  1. What is a path?
  2. What does .. mean?
  3. How do you autocomplete a path?
  4. How do you go up one directory?
  5. What command lists only names (dir flag)?
  6. True or False: On Windows, CMD uses backslashes (\) in paths, but forward slashes (/) are also accepted in some contexts.
  7. Explain the difference between an absolute path and a relative path.
  8. If you are in C:\Users\YourName\Documents and you type cd .., where do you end up?
  9. What happens when you press Tab while typing a folder name in Command Prompt?
  10. Describe a practical reason why understanding paths is important for a 3D printing workflow.
  11. What does C:\ mean in a path, and when would you use it?
  12. If a folder path contains spaces (e.g., Program Files), how do you navigate to it with cd?
  13. Explain what the prompt C:\Users\YourName> tells you about your current state.
  14. How would you navigate to your home directory from any location using a single command?
  15. What is the advantage of using relative paths (like ..) versus absolute paths in automation scripts?

Extension Problems

  1. Create a nested folder and practice cd into it by typing partial names and using Tab.
  2. Use dir /B /A:F to list only files in a folder.
  3. Save cd output (the path) to a file and open it in Notepad.
  4. Try cd into a folder whose name contains spaces; observe how quotes are handled.
  5. Create a short note file and open it from Command Prompt.
  6. Build a folder structure that mirrors your project organization; navigate to each level and document the path.
  7. Use echo %cd% to print your current path and save it to a file.
  8. Investigate special paths (e.g., %USERPROFILE%, %TEMP%); write down what each contains and when you’d use them.
  9. Compare absolute vs. relative paths by navigating to the same folder using each method; explain which is easier for automation.
  10. Create a batch file that changes to a frequently-used folder and lists its contents in one command; test it from different starting locations.
  11. Navigate to three different locations and at each one note the prompt, the path from cd, and verify you understand what each shows.
  12. Create a complex folder tree (at least 5 levels deep) and navigate it using only relative paths; verify your location at each step.
  13. Document all path shortcuts you know (C:\, .., .) and demonstrate each one works as expected.
  14. Write a guide for a peer on how to understand the Command Prompt and path notation without using GUI file explorer.
  15. Create a troubleshooting flowchart: if someone says “I don’t know where I am,” what commands do you give them to find out?

References

Helpful Resources


Lesson 1: Navigation — Moving Around Your File System


Duration: 1.5-2 hours (for screen reader users)
Prerequisites: Command Line Lesson Pre and Command Line Lesson 0
Learning Objectives:

  • Navigate confidently to any folder location
  • Understand and use relative versus absolute paths
  • Use shortcuts to move between common folders
  • Organize your file system logically

Core Navigation Commands

Command: cd (Change Directory)

cd FolderName          :: Go into a folder
cd ..                  :: Go up one level
cd \                   :: Go to root of current drive (e.g., C:\)
cd %USERPROFILE%       :: Go to home directory

Command: dir /B (List Contents)

dir /B                 :: List all names (one per line, screen-reader friendly)
dir /B /A:D            :: List only directories/folders
dir /B /A:F            :: List only files

Command: Show Current Location

cd                     :: Running cd with no arguments shows current path

Understanding Paths

Absolute Paths (Full Address)

An absolute path starts from the root and shows the complete location:

C:\Users\YourName\Documents\3DPrinting
  • C:\ — The C drive root
  • Users — First folder
  • YourName — Your user folder
  • Documents — Documents folder
  • 3DPrinting — Your 3D printing folder

Navigate there directly:

cd C:\Users\YourName\Documents\3DPrinting

Relative Paths (Directions From Here)

cd Documents\3DPrinting    :: Go into Documents, then into 3DPrinting
cd ..                      :: Go up one level
cd ..\..                   :: Go up two levels

Shortcuts:

  • . = Current folder
  • .. = Parent folder (up one level)
  • %USERPROFILE% = Your home folder

Common Navigation Patterns

Pattern 1: Navigating Down

C:\>cd Users
C:\Users>cd YourName
C:\Users\YourName>cd Documents
C:\Users\YourName\Documents>

Pattern 2: Navigating Up

C:\Users\YourName\Documents>cd ..
C:\Users\YourName>cd ..
C:\Users>cd ..
C:\>

Pattern 3: Jump to a Known Path

C:\Deep\Folder\Somewhere>cd C:\Users\YourName
C:\Users\YourName>

Pattern 4: Going Home

cd %USERPROFILE%

Special Folders and Shortcuts

%USERPROFILE%              :: Your home folder
%USERPROFILE%\Desktop      :: Your Desktop
%USERPROFILE%\Documents    :: Your Documents
%USERPROFILE%\Downloads    :: Your Downloads
%ProgramFiles%             :: Program Files folder
C:\                        :: Root of C drive

Tab Completion (Essential Skill)

  1. Type the first few characters of a folder name.
  2. Press Tab.
  3. Command Prompt completes it.

Example:

C:\Users\YourName>cd Doc  [press Tab]
C:\Users\YourName>cd Documents
  • Your screen reader announces the completed name immediately.
  • Press Tab multiple times to cycle through all matches.

Screen Reader Tips for Navigation

NVDA Users

  1. After each cd command, run cd alone to confirm location. Press NVDA+Home (Insert+Home) to read the current line.
  2. Press NVDA+Down Arrow to read through dir /B output.
  3. For long listings: dir /B > listing.txt, then notepad.exe listing.txt.

JAWS Users

  1. After each cd command, press Insert+Up Arrow to re-read the current line.
  2. Press Insert+Down Arrow repeatedly to read output line by line.
  3. For long listings: dir /B > listing.txt, then notepad.exe listing.txt.

Windows Narrator Users

  1. After each cd command, press Narrator+D (CapsLock+D) to read the current line.
  2. Press Narrator+R to read output from the current position.
  3. For long listings, always redirect to a file and open in Notepad — Notepad is more comfortable for Narrator users than reading directly from the terminal buffer.

Dolphin SuperNova Users

  1. After each cd command, press CapsLock+L to read the current line.
  2. Press CapsLock+Numpad Plus (say all) to read all output from the current position.
  3. For long listings: dir /B > listing.txt, then notepad.exe listing.txt.

Best Practice for All Screen Readers

Always confirm your location after moving:

cd FolderName
cd                        :: Verify your new location

Practice Exercises

Exercise 1: Basic Down Navigation

  1. cd %USERPROFILE%
  2. Run cd to see location.
  3. dir /B
  4. cd Documents
  5. Run cd to confirm.
  6. dir /B

Exercise 2: Using Tab Completion

  1. cd %USERPROFILE%
  2. Type cd Doc then press Tab.
  3. Press Enter.
  4. Run cd to confirm.

Exercise 3: Navigating Up

  1. Navigate several levels deep.
  2. Run cd to see full path.
  3. Use cd .. to go up one level at a time.
  4. Run cd after each step.

Exercise 4: Absolute Path Navigation

  1. Navigate deep (3+ levels).
  2. Run cd %USERPROFILE% to jump home.
  3. Run cd to confirm.

Exercise 5: Creating and Navigating a Structure

mkdir 3DPractice
cd 3DPractice
mkdir Models
cd Models
mkdir OpenSCAD
cd OpenSCAD

Run cd at each level. Then navigate back up using only cd ...


Checkpoint Questions

Answer all 10 before moving to Command Line Lesson 2:

  1. What is the difference between cd Documents and cd \?
  2. What does cd .. do?
  3. How do you go to your home folder from anywhere?
  4. What is an absolute path? Give an example.
  5. What is a relative path? Give an example.
  6. How do you confirm your current location?
  7. What does Tab completion do?
  8. How would you navigate 3 levels deep, then back home?
  9. What is the difference between . and ..?
  10. If you are lost, what command should you run first?

Extension Problems

  1. Create a folder with spaces in the name (e.g., My Projects) and navigate to it using quotes.
  2. Use Tab completion to navigate 5+ levels deep without typing full names.
  3. Create a script that saves cd output at each level to a log file.
  4. Navigate to the same destination using both absolute and relative paths from different starting locations.
  5. Build a complex folder tree (5+ levels) and navigate using only relative paths.
  6. Document the full paths to your 5 most-used folders.
  7. Create folders named 01Folder, 02Folder, etc. and practice Tab completion through them.
  8. Navigate to a folder, save the path with cd > mypath.txt, navigate away, then return using the saved path.
  9. Challenge: navigate to a destination using only relative paths without running cd to check at each step.
  10. Create a batch file that navigates to a project folder and lists its contents in one step.

Common Issues

“The system cannot find the path specified”

  • Check spelling with dir /B to see correct folder names.
  • Use Tab completion to avoid typos.
  • Use the absolute path: cd C:\Users\YourName\Documents.

“I’m lost”

cd

This always shows your current location.

Tab Completion Not Working

  • Type at least one character before pressing Tab.
  • Confirm the folder exists with dir /B.
  • Press Tab again to cycle through multiple matches.

Quick Reference

cd                         :: Show current location
cd FolderName              :: Go into a folder
cd ..                      :: Go up one level
cd ..\..                   :: Go up two levels
cd \                       :: Go to drive root
cd %USERPROFILE%           :: Go to home folder
dir /B                     :: List folder contents
dir /B /A:D                :: List only folders
dir /B /A:F                :: List only files

Next Steps

Complete all exercises, pass the checkpoint questions, then move to Command Line Lesson 2: File & Folder Manipulation.


Lesson 2: File and Folder Manipulation


Duration: 2-2.5 hours (for screen reader users)
Prerequisites: Command Line Lesson Pre, Command Line Lesson 0, Command Line Lesson 1

Learning Objectives:

  • Create, copy, move, and delete files and folders safely
  • Use wildcards to operate on multiple files
  • Understand dangerous operations and how to stay safe
  • Rename files and understand file extensions

Core File Manipulation Commands

Create Folders: mkdir

mkdir FolderName                     :: Create a single folder
mkdir Folder1 Folder2 Folder3        :: Create multiple folders at once
mkdir A\B\C                          :: Create nested folders (A, then B inside A, then C inside B)

Create Files: echo with Redirection

echo This is some content > filename.txt    :: Create a file with text content
echo. > emptyfile.txt                       :: Create an empty file

Note: echo. (echo followed immediately by a period, no space) creates an empty file. echo with a space would put a space character in the file.

Copy Files: copy

copy source.txt destination.txt          :: Copy a file to a new name
copy source.txt backup\                  :: Copy a file into a folder
copy *.txt backup\                       :: Copy all .txt files to backup folder

Copy Folders: xcopy

xcopy sourcefolder destinationfolder /E /I    :: Copy a folder and all its contents
  • /E copies all subdirectories including empty ones.
  • /I treats the destination as a folder (not a file) if it doesn’t exist.

Move and Rename: move

move oldname.txt newname.txt             :: Rename a file
move file.txt folder\                    :: Move a file into a folder
move *.txt archive\                      :: Move all .txt files to archive folder

move renames when both source and destination are in the same folder. It moves when the destination is a different folder.

Delete Files: del

Caution

The /Q flag suppresses the confirmation prompt — del /Q deletes immediately and silently. Only use /Q in scripts where you have already verified the targets; never use it interactively when learning.

del filename.txt                         :: Delete one specific file
del *.txt                                :: Delete all .txt files in current folder
del /Q *.tmp                             :: Delete quietly (no confirmation prompt)

Warning

del does not send files to the Recycle Bin. Deleted files are permanently gone with no undo. Always verify the target with dir /B before deleting.

Delete Folders: rmdir

rmdir foldername                         :: Delete an empty folder
rmdir /S /Q foldername                   :: Delete a folder and ALL its contents (no undo)

Warning

rmdir /S /Q permanently deletes a folder and all its contents with no confirmation and no undo. Always verify the exact folder name with dir /B first — one wrong character can delete the wrong folder entirely.


Safe File Operations

Caution

Check, then delete. Never run del or rmdir without first running dir /B to confirm exactly what you’re about to remove. Wildcards like del *.txt will delete every matching file instantly and permanently.

Rule 1: Always Check Before Deleting

dir /B                   :: See exactly what is here
dir /B *.txt             :: See exactly which .txt files exist
del *.txt                :: Only then delete

Rule 2: Make Backups First

mkdir backup
copy *.txt backup\       :: Copy all .txt files to a backup folder first
del *.txt                :: Now safe to delete originals

Rule 3: Test on One File First

del test-one-file.txt    :: Test deletion on a single file
dir /B                   :: Confirm it is gone

Only then proceed with bulk operations.


Using Wildcards

Wildcards let you operate on multiple files matching a pattern.

* Wildcard (Match Any Number of Characters)

dir /B *.txt             :: List all files ending in .txt
copy *.scad backup\      :: Copy all .scad files to backup
del *.tmp                :: Delete all .tmp files

? Wildcard (Match Exactly One Character)

dir /B file?.txt         :: Matches file1.txt, file2.txt, filea.txt, etc.
copy model?.scad models\ :: Copy model1.scad, model2.scad, etc.

Practical Examples

3DMake in Practice: Navigating a Project

Navigation commands are exactly what you need to explore and manage 3DMake projects:

REM Go to your project root
cd %USERPROFILE%\Documents\3d_projects\my_cube

REM See the project layout: src, build, 3dmake.toml
dir /B

REM Enter the source folder where your .scad model files live
cd src
dir /B

REM Open the main model in Notepad
3dm edit-model

REM Go back to project root, then check build output
cd ..
cd build
dir /B *.stl

REM Return to project root
cd ..

REM Use wildcards to find all projects with "cube" in the name
dir /B %USERPROFILE%\Documents\3d_projects\*cube*

Tab completion makes navigation fast: type cd %USERPROFILE%\Doc and press Tab.


Practical Examples

Example 1: Create a Project Structure

mkdir 3DProjects
cd 3DProjects
mkdir Models Prints Documentation Backups
dir /B /A:D

Example 2: Backup Before Editing

copy project.scad project-backup.scad    :: Create a backup copy
:: (edit project.scad)
copy project.scad project-v2.scad        :: Save a new versioned copy

Example 3: Organize Files by Type

mkdir scad-files
mkdir text-files
move *.scad scad-files\
move *.txt text-files\
dir /B /A:D

Practice Exercises

Exercise 1: Create a Folder Structure

  1. mkdir practice-session
  2. cd practice-session
  3. mkdir files documents models
  4. dir /B /A:D

Goal: Create organized folder structures confidently.

Exercise 2: Create and Copy Files

  1. echo Hello World > test.txt
  2. type test.txt
  3. copy test.txt test-backup.txt
  4. dir /B *.txt
  5. type test-backup.txt

Goal: Create and copy files without errors.

Exercise 3: Safe Deletion Practice

  1. echo content > file1.txt
  2. echo content > file2.txt
  3. echo content > file3.txt
  4. dir /B *.txt (confirm all three exist)
  5. del file1.txt (delete just one)
  6. dir /B *.txt (confirm only two remain)

Goal: Practice the “check, then delete” pattern.

Exercise 4: Wildcard Operations

3DMake in Practice: Organizing Your Projects

File management commands are essential for 3DMake project organization:

REM Create a new project from scratch
mkdir %USERPROFILE%\Documents\3d_projects\bottle_cap
cd %USERPROFILE%\Documents\3d_projects\bottle_cap
3dm new

REM Back up a working project before making big changes
cd %USERPROFILE%\Documents\3d_projects
xcopy /E /I bottle_cap bottle_cap_backup

REM Rename the main model file to something more specific
cd bottle_cap\src
rename main.scad bottle_cap.scad

REM List only .scad files to confirm the rename
dir /B *.scad

REM Delete a draft STL you no longer need
del %USERPROFILE%\Documents\3d_projects\bottle_cap\build\draft.stl

REM Build the renamed model (using the -m flag to specify the name)
cd %USERPROFILE%\Documents\3d_projects\bottle_cap
3dm build -m bottle_cap

REM See the fresh output in the build folder
dir /B build

Exercise 4: Wildcard Operations

  1. Create three files: echo a > doc1.txt, echo b > doc2.txt, echo c > doc3.txt
  2. dir /B *.txt
  3. mkdir archive
  4. copy *.txt archive\
  5. cd archive
  6. dir /B *.txt

Goal: Comfortable using wildcards for bulk operations.


Screen Reader Tips

NVDA Users

After file operations, run dir /B and press NVDA+Down Arrow to verify results. Redirect output to a file for complex verification: dir /B > check.txt, then notepad.exe check.txt.

JAWS Users

After file operations, run dir /B and press Insert+Down Arrow to read results. For complex output: dir /B > check.txt, then notepad.exe check.txt.

Windows Narrator Users

After file operations, run dir /B and press Narrator+R to read from the current position. Redirect to a file and open in Notepad for long output.

Dolphin SuperNova Users

After file operations, run dir /B and press CapsLock+Numpad Plus to read results. For long output: dir /B > check.txt, then notepad.exe check.txt.

Important

After any copy, move, or del operation, always verify with dir /B to confirm the expected result. Never assume an operation succeeded without checking — silent failures do occur.

General Tip for All Screen Readers

After any copy, move, or del operation, always verify with dir /B to confirm the expected result. Never assume an operation worked without checking.


Checkpoint Questions

  1. How do you create a folder?
  2. How do you copy a file?
  3. How do you rename a file?
  4. How do you delete a file safely (checking first)?
  5. What does * match in a wildcard pattern?
  6. What does ? match in a wildcard pattern?
  7. How would you copy all .scad files to a backup folder?
  8. What should you always do before deleting?
  9. How do you delete a folder and all its contents?
  10. Why is it important to create a backup before editing?

Extension Problems

  1. Create a nested folder structure (5+ levels) using a single mkdir command with backslashes.
  2. Create 10 files and organize them into subfolders using move with wildcards.
  3. Create a date-based backup strategy: copy all files to a folder named with today’s date.
  4. Use wildcards to select specific file types and copy them to separate organized folders.
  5. Create a file-renaming system (file001.txt, file002.txt, etc.) and practice moving them between folders.

Next Steps

Complete all exercises, pass the checkpoint questions, then move to Command Line Lesson 3: Input, Output & Redirection.


Lesson 3: Input, Output, and Piping


Duration: 1 class period Prerequisite: Command Line Lesson 2 (File and Folder Manipulation)


Learning Objectives

By the end of this lesson, you will be able to:

  • Use echo to print text to the screen
  • Use type to read file contents
  • Use > to redirect output into a file
  • Use | (pipe) to send one command’s output to another
  • Copy output to the clipboard with clip
  • Open files with a text editor from the command line

Commands Covered

CommandWhat It Does
echo textPrint text to the screen
type filenamePrint the contents of a file
> filenameRedirect output into a file (overwrites)
>> filenameAppend output to a file (adds to end)
|Pipe - send output from one command to the next
clipCopy piped input to the Windows clipboard
notepad filenameOpen a file in Notepad

echo - Printing Text

echo prints text to the screen. It is useful for testing, for writing text into files, and for understanding how piping works.

echo Hello, World
echo This is a test

type - Reading Files

type prints the contents of a file to the screen.

:: Read a text file
type %USERPROFILE%\Documents\notes.txt

:: Read an OpenSCAD file
type %USERPROFILE%\Documents\OpenSCAD_Projects\project0.scad

With a long file, use type filename | more to read it page by page (press Space to advance, Q to quit).


> - Redirecting Output to a File

The > symbol redirects output from the screen into a file instead.

:: Create a file with a single line
echo Author: Your Name > header.txt

:: Confirm the file was created and has content
type header.txt

Warning: > overwrites the file if it already exists. Use >> to append instead:

echo Date: 2025 >> header.txt
echo Project: Floor Marker >> header.txt
type header.txt

| - Piping

The pipe symbol | sends the output of one command to the input of the next. This lets you chain commands together.

:: List files and send the list to clip (copies to clipboard)
dir /B | clip
## 3DMake in Practice: Capturing Build Output

Piping and redirection are essential for working with 3DMake's output accessibly:

```cmd
REM Build and save the full log to a file so you can read it in Notepad
3dm build > build_log.txt
notepad build_log.txt

REM Build and slice, keeping only lines with errors or warnings
3dm build slice 2>&1 | findstr /I "error warning"

REM List all STL files produced so far
dir /B build\*.stl

REM Get a list of available printer profiles and save for reference
3dm list-profiles > profiles.txt
notepad profiles.txt

REM Get a list of material overlays (PLA, PETG, supports, etc.)
3dm list-overlays > overlays.txt
notepad overlays.txt

REM Get an AI description of your model and save it
3dm info > model_description.txt
notepad model_description.txt
:: List files and send the list to clip (copies to clipboard)
dir /B | clip

:: Now paste with Ctrl + V anywhere
:: Search within a file's contents using find
type project0.scad | find "cube"

clip - Copying to Clipboard

clip takes whatever is piped to it and puts it on the Windows clipboard.

:: Copy your current directory path to the clipboard
cd | clip

:: Copy a file listing to clipboard
dir /B | clip

:: Copy the contents of a file to clipboard
type notes.txt | clip

After any of these, press Ctrl + V in any application to paste.


Opening Files in Notepad

:: Open a file in Notepad
notepad %USERPROFILE%\Documents\notes.txt

:: Open a .scad file
notepad %USERPROFILE%\Documents\OpenSCAD_Projects\project0.scad

:: Create a new file and open it
echo. > new_notes.txt
notepad new_notes.txt

Step-by-step Tasks

  1. Create practice.txt with three lines using echo and >/>>.
  2. Read the file with type practice.txt.
  3. Pipe the file into find to search for a word.
  4. Copy the file contents to clipboard with type practice.txt | clip.
  5. Redirect dir /B into list.txt and open it in Notepad.

Checkpoints

  • After step 3 you should be able to find a keyword using piping.

Quiz - Lesson CMD.3

  1. What is the difference between > and >>?
  2. What does the pipe | do?
  3. How do you copy output to the clipboard?
  4. How would you page through long output?
  5. How do you suppress output (send it nowhere)?
  6. True or False: The pipe operator | connects the output of one command to the input of another.
  7. Explain why redirecting output to a file is useful for screen reader users.
  8. Write a command that would search for the word “sphere” in all .scad files in a directory.
  9. How would you count the number of lines in a file using CMD piping?
  10. Describe a practical scenario in 3D printing where you would pipe or redirect command output.
  11. What would be the difference in output between echo test > file.txt (run twice) vs echo test >> file.txt (run twice)? Show the expected file contents.
  12. Design a three-step piping chain: read a file, filter for specific content, and save the results; explain what each pipe does.
  13. You have a 500-line .scad file and need to find all instances of sphere() and count them. Write the command.
  14. Explain how clip is particularly valuable for screen reader users when working with file paths or long output strings.
  15. Describe how you would use pipes and redirection to create a timestamped backup report of all .stl files in a 3D printing project folder.

Extension Problems

  1. Use piping to count lines in a file (hint: type file.txt | find /C /V "").
  2. Save a long dir /B output and search it with find.
  3. Chain multiple pipes to filter and then save results.
  4. Practice copying different command outputs to clipboard and pasting.
  5. Create a small batch script that generates a report (counts of files by extension).
  6. Build a data processing pipeline: read a text file, filter rows, and export results; document each step.
  7. Write a batch script that pipes directory listing to count occurrences of each file extension; create a summary report.
  8. Create a log analysis command: read a log file, filter for errors, and save matching lines to a separate error log.
  9. Design a piping workflow for 3D printing file management: find .stl files, extract their names, and generate a report.
  10. Develop a reusable piping pattern library: create batch scripts for common filtering, sorting, and reporting patterns; test each with different inputs.
  11. Build a complex filter pipeline: read a .scad file, extract lines containing specific geometry commands, count each type, and output a summary to both screen and file.
  12. Create an interactive filtering tool: build a batch script that accepts a search term, pipes through multiple filters, and displays paginated results.
  13. Develop a performance analysis tool: use piping to combine file listing, metadata extraction, and statistical reporting; export results to a dated report file.
  14. Implement a comprehensive error-handling pipeline: read output, catch errors, log them separately, and generate a summary of successes vs failures.
  15. Design and execute a real-world project backup workflow: use piping to verify file existence, count files by type, generate a backup manifest, and create audit logs — all in one integrated command pipeline.

References

Helpful Resources


Lesson 4: Environment Variables, PATH, and Aliases


Estimated time: 30-45 minutes

Learning Objectives

  • Read environment variables with %VARNAME%
  • Inspect and verify programs in the PATH
  • Create temporary aliases with doskey and understand making them persistent via a startup script

Materials

  • Command Prompt

Step-by-step Tasks

  1. Show your username and home path with echo %USERNAME% and echo %USERPROFILE%.
  2. Inspect echo %PATH% and identify whether openscad or code would be found.
  3. Run where openscad and note the result.
  4. Create a temporary alias: doskey preview=openscad $* and test preview myfile.scad.
  5. Open your startup script (notepad.exe autorun.bat) and add the doskey line to make it persistent (advanced).

Checkpoints

  • After step 3 you can determine whether a program will be found by PATH.

Quiz - Lesson CMD.4

3DMake in Practice: DOSKEY Macros for 3DMake

DOSKEY macros give you fast shortcuts for your most-used 3DMake commands:

REM Quick macro to jump to your 3D projects folder
doskey 3dp=cd %USERPROFILE%\Documents\3d_projects

REM Quick macro to run the full build-slice-print pipeline
doskey 3dprint=3dm build slice print

REM Quick macro to build then describe the model
doskey 3dinfo=3dm build $T 3dm info

REM Test the macros in the current session
3dp
3dprint

REM To make these permanent, add them to a startup batch file
notepad %USERPROFILE%\cmd_startup.cmd
REM Add the doskey lines, save, and then register via Windows Registry:
REM HKCU\Software\Microsoft\Command Processor\AutoRun = %USERPROFILE%\cmd_startup.cmd

Checkpoints

  • After step 3 you can determine whether a program will be found by PATH.

Quiz - Lesson CMD.4

  1. How do you print an environment variable?
  2. What is the purpose of PATH?
  3. How do you check whether openscad is available?
  4. How do you create a temporary alias in CMD?
  5. Where would you make an alias permanent?
  6. True or False: Environment variable names in CMD are case-sensitive.
  7. Explain why having a program in your PATH is useful compared to always using its full file path.
  8. Write a command that would create a doskey alias called slicer for the OpenSCAD executable.
  9. What file or technique would you use to make a doskey alias persist across CMD sessions?
  10. Describe a practical benefit of using the %TEMP% directory for temporary files in a 3D printing workflow.
  11. You have a custom batch script at C:\Scripts\backup_models.bat that you want to run from anywhere as backup-now. What steps would you take to make this work?
  12. Explain the difference between setting an environment variable in the current session with set vs. using setx for permanence.
  13. Design a strategy for managing multiple 3D printing projects, each with different tool paths and directories; show how to structure environment variables for each.
  14. If a program is not found by where, what are the possible reasons, and how would you troubleshoot?
  15. Describe how you would verify that your CMD autorun script is loading correctly and how to debug issues if aliases or environment variables don’t appear after opening a new CMD session.

Extension Problems

  1. Add a folder to PATH for a test program (describe steps; do not change system PATH without admin).
  2. Create a short autorun snippet that sets two aliases and test re-opening CMD.
  3. Use where to list the path for several common programs.
  4. Explore %TEMP% and create a file there.
  5. Save a copy of your current PATH to a text file and examine it in your editor.
  6. Create a CMD autorun script that loads custom aliases and environment variables for your 3D printing workflow; test it in a new session.
  7. Build a “project profile” batch script that sets environment variables for CAD, slicing, and print directories; switch between profiles for different projects.
  8. Write a batch script that audits your current environment variables and creates a summary report of what’s set and why.
  9. Design a custom alias system using doskey for common 3D printing commands; document the aliases and their purposes.
  10. Create a profile migration guide: document how to export and import your CMD aliases and variables across machines for consistent workflows.
  11. Implement a safe PATH modification script: create a utility that allows you to add/remove directories from PATH for the current session only; show how to make it permanent with setx.
  12. Build a comprehensive autorun framework: create separate .bat files for aliases, environment variables, and helper macros; have your main autorun load all of them.
  13. Develop an environment validation tool: write a batch script that checks whether all required programs (OpenSCAD, slicers, etc.) are accessible via PATH; report findings and suggest fixes.
  14. Create a project-switching alias system: design a batch script that changes all environment variables and aliases based on the current project; test switching between multiple projects.
  15. Build a troubleshooting guide: create a batch script that exports your current environment state (variables, aliases, PATH) to a timestamped file, allowing you to compare states before and after changes.

References

Helpful Resources


Lesson 5: Filling in the Gaps — Startup Scripts, History, and Useful Tricks


Estimated time: 30-45 minutes

Learning Objectives

  • Use history and abort commands (doskey /history, F7, Ctrl+C)
  • Inspect and edit your CMD autorun script for persistent settings
  • Run programs by full path using the start or call operator
  • Handle common screen reader edge cases when using the terminal

Materials

  • Command Prompt and an editor (Notepad/VS Code)

Step-by-step Tasks

  1. Run several simple commands (e.g., cd, dir /B, echo hi) then press F7 or run doskey /history to view them.
  2. Use F8 to search back through history, or use the up-arrow to re-run a previous command.
  3. Practice aborting a long-running command with Ctrl + C (for example, ping 8.8.8.8).
  4. Open your autorun script: notepad.exe autorun.bat; if it doesn’t exist, create it with echo. > autorun.bat.
  5. Add a persistent alias line to your autorun script (example: doskey preview=openscad $*), save, and configure CMD to use it by registering it in the registry (advanced).

Checkpoints

  • After step 2 you can re-run a recent command from history.
  • After step 5 your alias should persist across CMD sessions.

Quiz - Lesson CMD.5

  1. How do you view the command history in CMD?
  2. Which key combination aborts a running command?
  3. What does echo %CMDCMDLINE% show?
  4. How does the start command help run executables?
  5. What is one strategy if terminal output stops being announced by your screen reader?
  6. True or False: Using Ctrl+C permanently deletes any files created by the command you abort.
  7. Explain the difference between pressing F7 and running doskey /history in CMD.
  8. If you add a doskey macro to your autorun script but it doesn’t take effect after opening a new CMD window, what should you verify?
  9. Write a command that would run a program at the path C:\Program Files\OpenSCAD\openscad.exe directly.
  10. Describe a practical workflow scenario where having keyboard shortcuts (doskey macros) in your autorun script would save time.
  11. Explain how to re-run the 5th command from your history using F7 and selection, and what would happen if that command had file operations (creates/deletes).
  12. Design an autorun initialization strategy that separates utilities for different projects; explain how you would switch between them.
  13. Walk through a troubleshooting workflow: your screen reader stops announcing output after running a long command. What steps would you take to diagnose and resolve the issue?
  14. Create a safety checkpoint system: before any destructive operation (mass delete, overwrite), how would you use autorun macros and history to verify the command is correct?
  15. Develop a comprehensive capstone scenario: integrate everything from Command Line Lesson 0 through Command Line Lesson 5 (navigation, file operations, piping, environment setup, history) to design an automated 3D printing project workflow with error handling and logging.

Extension Problems

  1. Add a doskey macro and an environment variable change to your autorun script and document the behavior after reopening CMD.
  2. Create a short batch script that automates creating a project folder and an initial .scad file.
  3. Experiment with running OpenSCAD by full path using start and by placing it in PATH; compare results.
  4. Practice redirecting help output to a file and reading it in Notepad for screen reader clarity.
  5. Document three screen reader troubleshooting steps you used and when they helped.
  6. Build a comprehensive CMD autorun script that includes aliases, environment variables, and helper macros for your 3D printing workflow.
  7. Create a batch script that troubleshoots common CMD issues (missing commands, permission errors, command not found); test at least three scenarios.
  8. Write a batch script that coordinates multiple tasks: creates a project folder, starts OpenSCAD, and opens a notes file.
  9. Design a screen-reader accessibility guide for CMD: document commands, outputs, and accessible navigation patterns.
  10. Develop an advanced CMD workflow: implement error handling, logging, and confirmation prompts for risky operations.
  11. Implement an “undo” system using history: create a batch script that logs destructive commands (del, move, copy /Y) and allows you to review the last operation.
  12. Build an autorun debugger: create a script that compares two CMD sessions’ environment states (variables, aliases, macros) to identify what loaded/failed to load.
  13. Develop a multi-project autorun manager: design a system where you can switch entire environments (paths, aliases, variables) for different 3D printing projects by running a single script.
  14. Create a comprehensive accessibility analyzer: write a batch script that tests whether key CMD commands produce screen-reader-friendly output; document workarounds for commands that don’t.
  15. Design a complete capstone project: build an integrated automation suite that manages a 3D printing workflow (project setup, file organization, CAD/slicing tool automation, output logging, error recovery, and audit trails) with full error handling and documentation.

References

Helpful Resources


Lesson 6: Advanced Techniques — Batch Scripts, Subroutines, and Professional Workflows


Duration: 4-4.5 hours (for screen reader users) Prerequisites: Complete Command Line Lesson 0 through Command Line Lesson 5 Skill Level: Advanced intermediate

3DMake in Practice: Automating Your Print Workflow

Use a batch script to fully automate a 3DMake workflow across multiple projects:

@echo off
REM batch_print.bat - build and print every 3DMake project subfolder

set PROJECTS=%USERPROFILE%\Documents\3d_projects

for /D %%P in ("%PROJECTS%\*") do (
    echo Processing: %%~nxP
    cd "%%P"

    3dm build slice > build_log.txt 2>&1
    if %ERRORLEVEL% EQU 0 (
        echo   OK - sending to printer
        3dm print
    ) else (
        echo   FAILED - check build_log.txt
        notepad build_log.txt
    )
)

echo Batch complete.

Save as batch_print.bat and run by typing batch_print. This script uses loops, conditionals, and output redirection — all from this lesson.

This lesson extends CMD skills to professional-level workflows. You’ll learn to automate complex tasks, write reusable batch scripts, and integrate tools for 3D printing workflows.


Learning Objectives

By the end of this lesson, you will be able to:

  • Create and run batch files (.bat files)
  • Write subroutines that accept parameters
  • Use loops to repeat tasks automatically
  • Automate batch processing of 3D models
  • Debug batch scripts when something goes wrong
  • Create professional workflows combining multiple tools

Batch Script Basics

What’s a Batch Script?

A batch file (.bat) contains multiple CMD commands that run in sequence. Instead of typing commands one by one, you put them in a file and run them all at once.

Why use batch scripts?

  • Repeatability: Run the same task 100 times identically
  • Documentation: Commands are written down for reference
  • Complexity: Combine many commands logically
  • Automation: Schedule scripts to run automatically

Creating Your First Batch Script

Step 1: Open a text editor

notepad.exe my-first-script.bat

Step 2: Type this script

@echo off
:: This is a comment - screen readers will read it
echo Script is running!
cd
dir /B
echo Script is done!

Step 3: Save the file

  • In Notepad: Ctrl+S
  • Make sure filename ends in .bat
  • Save in an easy-to-find location (like Documents)

Step 4: Run the script

my-first-script.bat

What happens: CMD runs each command in sequence and shows output.

Important: @echo off

On some scripts, each command is echoed before running. @echo off at the top suppresses this, showing only output — not the commands themselves.

@echo off
:: Now only output is shown, not each command
echo Hello!

Variables and Parameters

Using Variables

Variables store values you want to use later.

Example script:

@echo off
set mypath=C:\Users\YourName\Documents
cd %mypath%
echo I am now in:
cd
dir /B

Breaking it down:

  • set mypath=... assigns the variable
  • %mypath% uses the variable (wraps it in %)
  • Variables in CMD are always referenced with %VARNAME%

Subroutines with Parameters

A subroutine is reusable code that you can call with different inputs using :label and call.

Example: A subroutine that lists files in a folder

@echo off
call :ListFolder "C:\Users\YourName\Documents"
call :ListFolder "C:\Users\YourName\Downloads"
goto :eof

:ListFolder
echo Contents of: %~1
cd /D %~1
dir /B
goto :eof

What’s happening:

  • :ListFolder marks the start of the subroutine
  • %~1 is the first argument passed to the subroutine
  • call :ListFolder "path" calls the subroutine with a path
  • goto :eof exits the subroutine (or script)

Screen reader tip: When you call a subroutine, CMD will announce the results just like any command.


Loops - Repeating Tasks

Loop Over Files

Imagine you have 10 SCAD files and want to print their names. You could do it 10 times manually, or use a loop.

Example: Print every .scad file in a folder

@echo off
for %%f in (*.scad) do (
    echo === File: %%f ===
    type %%f
    echo.
)

What’s happening:

  • for %%f in (*.scad) do iterates over each .scad file
  • %%f is the loop variable (use %f in interactive CMD, %%f in batch files)
  • Inside the parentheses, do something with each file

Loop with a Counter

Example: Do something 5 times

@echo off
for /L %%i in (1,1,5) do (
    echo This is iteration number %%i
)

What’s happening:

  • for /L %%i in (start,step,end) counts from start to end
  • %%i is the counter variable

Real-World Example - Batch Processing SCAD Files

Scenario

You have 10 OpenSCAD (.scad) files in a folder. You want to:

  1. List them all
  2. Check how many there are
  3. For each one, verify it exists

The Script

@echo off
set scadFolder=C:\Users\YourName\Documents\3D_Projects
set count=0

echo Processing SCAD files in: %scadFolder%
echo.

for %%f in (%scadFolder%\*.scad) do (
    if exist "%%f" (
        echo  Found: %%~nxf
        set /A count+=1
    ) else (
        echo  Missing: %%~nxf
    )
)

echo.
echo Total files found: %count%
echo Batch processing complete!

Breaking it down:

  • set scadFolder=... = where to look
  • for %%f in (...\*.scad) = find all .scad files
  • if exist "%%f" = check if file exists
  • %%~nxf = just the filename with extension (not the full path)
  • set /A count+=1 = increment the counter

Running the Script

  1. Save as batch-process.bat

  2. Edit scadFolder to match your real folder

  3. Run it:

    batch-process.bat
    

Screen reader output:

Processing SCAD files in: C:\Users\YourName\Documents\3D_Projects

 Found: model1.scad
 Found: model2.scad
 Found: model3.scad
[... more files ...]

Total files found: 10
Batch processing complete!

Error Handling

Checking Error Levels

What if something goes wrong? Use errorlevel checks:

Example:

@echo off
type C:\nonexistent\path\file.txt
if %errorlevel% neq 0 (
    echo Error: Could not read file
    echo Errorlevel: %errorlevel%
)

What’s happening:

  • After any command, %errorlevel% holds 0 for success or non-zero for failure
  • if %errorlevel% neq 0 checks for failure
  • Handle the error gracefully

Screen reader advantage: Errors are announced clearly instead of crashing silently.

Validating Input

Example: Make sure a folder exists before processing

@echo off
set folderPath=C:\Users\YourName\Documents

if not exist "%folderPath%\" (
    echo Error: Folder does not exist: %folderPath%
    goto :eof
)

echo Processing folder: %folderPath%
dir /B "%folderPath%"

What’s happening:

  • if not exist "%folderPath%\" checks if folder exists (trailing \ ensures it’s a folder)
  • goto :eof exits the script early if error

Debugging Batch Scripts

Common Errors and Solutions

Error 1: “Command not found”

Cause: Typo in command name or program not in PATH

Fix: Check spelling and verify PATH

:: Wrong:
dri /B

:: Correct:
dir /B

Error 2: “Variable is empty”

Cause: Variable was never set or has a typo

Fix: Make sure variable is set before using it

set myvar=hello
echo %myvar%

Error 3: “The system cannot find the path specified”

Cause: Wrong folder path

Fix: Verify path exists

:: Check if path exists:
if exist "C:\Users\YourName\Documents\" echo Path exists

Error 4: “Access denied”

Cause: Don’t have permission

Fix: Run CMD as administrator

  • Right-click Command Prompt -> Run as administrator

Debugging Technique: Trace Output

Add echo statements to track what’s happening:

@echo off
set path_var=C:\Users\YourName\Documents
echo Starting script. Path is: %path_var%

for %%f in (%path_var%\*) do (
    echo Processing: %%f
    :: Do something with %%f
    echo Done with: %%f
)

echo Script complete

Your screen reader will announce each step, so you know where errors happen.


Creating Professional Workflows

Example 1: Automated Project Setup

Scenario: You start a new 3D printing project regularly. Instead of creating folders manually:

@echo off
set /p projectName=Enter project name: 
set baseFolder=C:\Users\YourName\Documents\3D_Projects
set projectFolder=%baseFolder%\%projectName%

:: Create folder structure
mkdir "%projectFolder%"
mkdir "%projectFolder%\designs"
mkdir "%projectFolder%\output"
mkdir "%projectFolder%\notes"

:: Create a README
echo # %projectName% > "%projectFolder%\README.txt"
echo. >> "%projectFolder%\README.txt"
echo Created: %date% >> "%projectFolder%\README.txt"
echo. >> "%projectFolder%\README.txt"
echo ## Designs >> "%projectFolder%\README.txt"
echo All .scad files go here. >> "%projectFolder%\README.txt"
echo. >> "%projectFolder%\README.txt"
echo ## Output >> "%projectFolder%\README.txt"
echo STL and other exports go here. >> "%projectFolder%\README.txt"

echo Project setup complete: %projectFolder%

What it does:

  • Prompts for a project name
  • Creates folder structure for a new project
  • Sets up subfolders for designs, output, notes
  • Creates a README file automatically

Example 2: Batch File Verification

Scenario: Before processing, verify all required files exist:

@echo off
set projectFolder=C:\Users\YourName\Documents\3D_Projects\MyKeychain
set allGood=1

for %%i in (README.txt designs output notes) do (
    if exist "%projectFolder%\%%i" (
        echo  Found: %%i
    ) else (
        echo  Missing: %%i
        set allGood=0
    )
)

if %allGood%==1 (
    echo All checks passed!
) else (
    echo Some files are missing!
)

Screen Reader Tips for Batch Scripts

Making Script Output Readable

Problem: Script runs but output scrolls too fast or is hard to follow

Solution 1: Save to file

my-script.bat > output.txt
notepad.exe output.txt

Solution 2: Use echo with clear sections

echo ========== STARTING ==========
echo.
:: ... script ...
echo.
echo ========== COMPLETE ==========

Solution 3: Pause between major sections

echo Pausing... Press any key to continue
pause > nul

Your screen reader will announce the pause, give you time to read output.

Announcing Progress

For long-running scripts:

@echo off
set count=0
for %%f in (*.scad) do (
    set /A count+=1
    echo Processing file %%f
)
echo All %count% files processed!

Practice Exercises

Exercise 1: Your First Batch Script

Goal: Create and run a simple batch script

Steps:

  1. Create file: notepad.exe hello.bat

  2. Type:

    @echo off
    echo Hello from my first CMD batch script!
    cd
    dir /B
    
  3. Save and run: hello.bat

Checkpoint: You should see output for each command.

Exercise 2: Script with a Variable

Goal: Use a variable to make the script flexible

Steps:

  1. Create file: notepad.exe smart-listing.bat

  2. Type:

    @echo off
    set targetFolder=C:\Users\YourName\Documents
    echo Listing contents of: %targetFolder%
    dir /B "%targetFolder%"
    
  3. Edit targetFolder to a real folder on your computer

  4. Run: smart-listing.bat

Checkpoint: You should see listing of that specific folder.

Exercise 3: Subroutine

Goal: Create a reusable subroutine

Steps:

  1. Create file: notepad.exe navigate.bat

  2. Type:

    @echo off
    call :GoTo "C:\Users\YourName\Documents"
    call :GoTo "C:\Users\YourName\Downloads"
    goto :eof
    
    :GoTo
    if exist "%~1\" (
        cd /D "%~1"
        echo Now in:
        cd
        echo Contents:
        dir /B
    ) else (
        echo Path does not exist: %~1
    )
    goto :eof
    
  3. Run: navigate.bat

Checkpoint: Both subroutine calls should work, showing contents of each folder.

Exercise 4: Loop

Goal: Use a loop to repeat an action

Steps:

  1. Create file: notepad.exe repeat.bat

  2. Type:

    @echo off
    echo Demonstrating a loop:
    for /L %%i in (1,1,5) do (
        echo Iteration %%i: Hello!
    )
    echo Loop complete!
    
  3. Run: repeat.bat

Checkpoint: Should print “Iteration 1” through “Iteration 5”.

Exercise 5: Real-World Script

Goal: Create a useful script for a real task

Steps:

  1. Create a folder: mkdir C:\Users\YourName\Documents\TestFiles

  2. Create some test files:

    echo test > C:\Users\YourName\Documents\TestFiles\file1.txt
    echo test > C:\Users\YourName\Documents\TestFiles\file2.txt
    echo test > C:\Users\YourName\Documents\TestFiles\file3.txt
    
  3. Create script: notepad.exe report.bat

  4. Type:

    @echo off
    set folder=C:\Users\YourName\Documents\TestFiles
    set count=0
    
    echo === FILE REPORT ===
    echo Folder: %folder%
    echo.
    echo Files:
    for %%f in ("%folder%\*") do (
        echo   - %%~nxf
        set /A count+=1
    )
    echo.
    echo Total: %count% files
    echo === END REPORT ===
    
  5. Run: report.bat

Checkpoint: Should show report of all files in the test folder.


Quiz - Lesson CMD.6

  1. What is a CMD batch script?
  2. What file extension do CMD batch scripts use?
  3. What is a variable in a batch script and how do you create one?
  4. What is a subroutine (:label) and why would you use one?
  5. How do you run a batch script?
  6. What is a for loop and what does for %%f in (*.scad) do do?
  7. What does if exist do?
  8. How do you handle errors in a batch script?
  9. When would you use if %errorlevel% neq 0?
  10. What technique makes batch script output readable for screen readers?

Extension Problems

  1. Auto-Backup Script: Create a batch script that copies all files from one folder to another, announcing progress
  2. File Counter: Write a subroutine that counts files by extension (.txt, .scad, .stl, etc.)
  3. Folder Cleaner: Batch script that deletes files older than 30 days (with user confirmation)
  4. Project Template: Subroutine that creates a complete project folder structure with all needed files
  5. Batch Rename: Script that renames all files in a folder according to a pattern
  6. Log Generator: Create a script that records what it does to a log file for later review
  7. Scheduled Task: Set up a batch script to run automatically every day at a specific time
  8. File Verifier: Check that all SCAD files in a folder have corresponding STL exports
  9. Report Generator: Create a summary report of all projects in a folder
  10. Error Tracker: Script that lists all commands that had errors and logs them with timestamps

Important Notes

  • Always test scripts on small sets of files first before running them on important data
  • Save your work regularly — use version naming if possible
  • Test error handling — make sure errors don’t crash silently
  • Document your scripts — use :: comments so you remember what each part does
  • Backup before batch operations — if something goes wrong, you have the original

References


Next Steps: After mastering this lesson, explore advanced batch scripting, scheduled tasks, and 3D printing integration in the main curriculum.


Unit Exam — Comprehensive Assessment


Estimated time: 60-90 minutes

Key Learning Outcomes Assessed

By completing this unit test, you will demonstrate:

  1. Understanding of file system navigation and path concepts
  2. Proficiency with file and folder manipulation commands
  3. Ability to redirect and pipe command output
  4. Knowledge of environment variables and aliases
  5. Screen-reader accessibility best practices in terminal environments
  6. Problem-solving and command chaining skills

Target Audience

Users who have completed Command Line Lesson 0 through Command Line Lesson 6 and need to demonstrate mastery of Command Prompt fundamentals.

Instructions

Complete all sections below. For multiple choice, select the best answer. For short answers, write one to two sentences. For hands-on tasks, capture evidence (screenshots or output files) and submit alongside your answers.


Part A: Multiple Choice Questions (20 questions)

Select the best answer for each question. Each question is worth 1 point.

  1. What is the primary purpose of the PATH environment variable?

    • A) Store your home directory location
    • B) Tell the shell where to find executable programs
    • C) Configure the visual appearance of the terminal
    • D) Store the current working directory name
  2. Which command shows your current working directory in CMD?

    • A) dir /B
    • B) cd (with no arguments)
    • C) pwd
    • D) whoami
  3. What does %USERPROFILE% represent in CMD?

    • A) The root directory
    • B) The current directory
    • C) The parent directory
    • D) Your home directory
  4. How do you list only file names (not full details) in a screen-reader-friendly way?

    • A) dir
    • B) dir /B
    • C) dir /L
    • D) type /B
  5. Which command creates a new empty file in CMD?

    • A) mkdir filename
    • B) echo. > filename
    • C) touch filename
    • D) new filename
  6. What is the difference between > and >>?

    • A) > redirects to file, >> displays on screen
    • B) > overwrites a file, >> appends to a file
    • C) They do the same thing
    • D) > is for text, >> is for binary
  7. What does the pipe operator | do?

    • A) Creates a folder
    • B) Sends the output of one command to the input of another
    • C) Deletes files matching a pattern
    • D) Lists all processes
  8. Which command copies a file in CMD?

    • A) move
    • B) del
    • C) copy
    • D) cd
  9. How do you rename a file from oldname.txt to newname.txt in CMD?

    • A) copy oldname.txt newname.txt
    • B) move oldname.txt newname.txt
    • C) rename oldname.txt newname.txt
    • D) Both B and C are correct
  10. What is the purpose of find in CMD piping?

    • A) Find files in a directory
    • B) Search for text patterns within output
    • C) Find a string to copy to clipboard
    • D) Find which shell to use
  11. Which key allows you to autocomplete a path in CMD?

    • A) Ctrl + A
    • B) Ctrl + E
    • C) Tab
    • D) Space
  12. How do you copy text to the Windows clipboard from CMD?

    • A) type filename > clipboard
    • B) type filename | clip
    • C) copy filename
    • D) type filename | paste
  13. What does where openscad do?

    • A) Opens the OpenSCAD application
    • B) Gets help about the openscad command
    • C) Locates the full path of the openscad executable
    • D) Lists all available commands
  14. Which wildcard matches any single character?

    • A) *
    • B) ?
    • C) %
    • D) #
  15. What is the purpose of the start command?

    • A) Run a script or executable, optionally in a new window
    • B) Execute all commands in parallel
    • C) Combine multiple commands
    • D) Create an alias
  16. How do you create a temporary alias (macro) in CMD?

    • A) alias preview='openscad'
    • B) doskey preview=openscad $*
    • C) set preview=openscad
    • D) macro preview openscad
  17. How can doskey macros be made to persist across CMD sessions?

    • A) They are automatically saved
    • B) By adding them to a startup batch script registered as an autorun
    • C) By using the Windows Control Panel
    • D) Doskey macros cannot be made permanent
  18. How do you abort a long-running command in CMD?

    • A) Press Escape
    • B) Press Ctrl + X
    • C) Press Ctrl + C
    • D) Press Alt + F4
  19. What command shows the history of previously run commands in CMD?

    • A) history
    • B) doskey /history
    • C) F7 (opens history popup)
    • D) Both B and C are correct
  20. How do you make an environment variable permanent in CMD (for all future sessions)?

    • A) Use set in the terminal every time
    • B) Use setx to write it to the registry
    • C) Use the Windows Control Panel only
    • D) Environment variables cannot be made permanent in CMD

Part B: Short Answer Questions (10 questions)

Answer each question in one to two sentences. Each question is worth 2 points.

  1. Explain the difference between absolute and relative paths. Give one example of each.

  2. Why is dir /B preferred over dir for screen reader users? Describe what flag you would add to list only files.

  3. What is the purpose of redirecting output to a file, and give an example of when you would use > instead of >>?

Warning

rmdir /S /Q C:\Documents\my_folder permanently deletes the folder and all its contents with no confirmation prompt and no undo. Always run dir /B C:\Documents\my_folder first to confirm what you’re about to destroy.

  1. Describe what would happen if you ran rmdir /S /Q C:\Documents\my_folder and why this command should be used carefully.

  2. How would you search for all files with a .scad extension in your current directory? Write the command.

  3. Explain what happens when you pipe the output of dir /B into clip. What would you do next?

  4. What is an environment variable, and give one example of how you might use it in CMD.

  5. If a program is not in your PATH, what two methods could you use to run it from CMD?

  6. Describe how you would open a file in Notepad and also add a line to it from CMD.

  7. What is one strategy you would use if your screen reader stops announcing terminal output while using CMD?


Part C: Hands-On Tasks (10 tasks)

Complete each task and capture evidence (screenshots, output files, or command transcripts). Each task is worth 3 points.

Tasks 1-5: File System and Navigation

  1. Create a folder structure %USERPROFILE%\Documents\CMD_Assessment\Projects using a single command. Capture the dir /B output showing the creation.

  2. Create five files named project_1.scad, project_2.scad, project_3.txt, notes_1.txt, and notes_2.txt inside the Projects folder. Use wildcards to list only .scad files, then capture the output.

  3. Copy the entire Projects folder to Projects_Backup using xcopy /E /I. Capture the dir /B output showing both folders exist.

  4. Move (rename) project_1.scad to project_1_final.scad. Capture the dir /B output showing the renamed file.

  5. Delete notes_1.txt and notes_2.txt using a single del command with wildcards. Capture the final dir /B output.

Tasks 6-10: Advanced Operations and Scripting

  1. Create a file called my_data.txt with at least four lines using echo and >>. Then read it with type my_data.txt and capture the output.

  2. Use find to search for a keyword (e.g., “project”) in my_data.txt and pipe the results to clip. Paste the results into Notepad and capture a screenshot.

  3. List all files in the Projects folder and redirect the output to projects_list.txt. Open it in Notepad and capture a screenshot of the file.

  4. Create a temporary doskey alias called mydir that runs dir /B, test it, and capture the output. Then explain what would be required to make it persistent.

  5. Run help dir and redirect the output to help_output.txt. Open the file in Notepad and capture a screenshot showing at least the first page of help content.


Grading Rubric

SectionQuestionsPoints EachTotal
Multiple Choice20120
Short Answer10220
Hands-On Tasks10330
Total40-70

Passing Score: 49 points (70%)


Helpful Resources for Review


Submission Checklist

  • All 20 multiple choice questions answered
  • All 10 short answer questions answered (1-2 sentences each)
  • All 10 hands-on tasks completed with evidence captured
  • Files/screenshots organized and labeled clearly
  • Submission includes this checklist

Part 3 — Git Bash


Last Updated: February 2026
Total Duration: 30–45 hours of instruction and practice (for screen reader users)
Target Users: Anyone using a screen reader — NVDA, JAWS, Windows Narrator, and Dolphin SuperNova are all covered throughout this curriculum.
Platform: Git Bash on Windows (commands transfer directly to macOS Terminal and Linux)
Alternate to: PowerShell curriculum and CMD curriculum (same concepts, Bash/Unix syntax)

This single file contains the complete Git Bash Foundation curriculum in reading order. All lessons, quizzes, extension problems, and the unit exam are included. No additional files are needed.


Table of Contents

SectionTitleEstimated Time
Screen Reader Accessibility GuideNVDA, JAWS, Narrator, and SuperNova reference for Git Bash1–1.5 hours
Tutorial: Git Bash Quick StartPrompt orientation, core commands, path concepts30–45 minutes
Lesson Pre: Your First TerminalInstalling Git Bash, opening it, first commands1.5–2 hours
Lesson 0: Getting StartedPaths, ~, ./, ../, tab completion20–30 minutes
Lesson 1: Navigationpwd, cd, ls and flags, wildcards1 class period
Lesson 2: File and Folder Manipulationtouch, mkdir, cp, mv, rm, rmdir30–45 minutes
Lesson 3: Input, Output, and Pipingecho, cat, >, >>, `, clip, grep`
Lesson 4: Environment Variables and Aliases$VARNAME, PATH, which, alias, .bashrc30–45 minutes
Lesson 5: Filling in the Gapshistory, Ctrl+R, Ctrl+C, .bashrc, ./30–45 minutes
Lesson 6: Advanced TechniquesShell scripts, functions, loops, professional workflows4–4.5 hours
Unit ExamComprehensive assessment — Lessons 0 through 660–90 minutes

Total: approximately 30–45 hours including practice exercises


How to Use This File

If you have never used a terminal before: start with the Accessibility Guide, then the Tutorial, then Lesson Pre. Read in order from the top — each lesson builds on the previous one.

If you have used a terminal (CMD or PowerShell) but not Git Bash: read the Tutorial section for the key differences (Unix paths, forward slashes, ls vs dir, cat vs type). Then start at Lesson 0.

If you are experienced with Bash on macOS or Linux: jump to the Accessibility Guide for screen-reader-specific techniques, then skip to whatever lesson covers your gap.

Reference while working: the Accessibility Guide and Tutorial contain material you will return to throughout the curriculum. Bookmark those sections.

CMD or PowerShell users: this curriculum covers the same concepts as the CMD and PowerShell curricula but uses Bash/Unix syntax. Commands learned here transfer directly to macOS Terminal and Linux. Choose one pathway and stay consistent.


Curriculum Rules (Read These First)

Important

Rule 1 — Always know where you are. Start every session with pwd. If you don’t know your current path, you risk operating on the wrong files or folders.

Rule 1 — Always know where you are.
Every session, first thing: pwd. If you do not know your path, you will get lost.

Warning

There is no Recycle Bin in the terminal. Files deleted with rm are permanently gone immediately — no undo, no recovery. Always run ls -1 to confirm exactly what you’re about to delete before running any rm command.

Rule 2 — Check before you delete.
Before any rm or rm -r command: ls -1 to confirm exactly what you are about to remove. Deleted files are gone immediately — there is no Recycle Bin in the terminal.

Tip

Always use ls -1 (the number 1, not the letter L) — never bare ls. The -1 flag outputs one name per line, which screen readers can follow reliably. Bare ls outputs a multi-column grid that is difficult to navigate audibly.

Rule 3 — Use ls -1 for listings.
Always ls -1 — never bare ls. The -1 flag gives one name per line, which all screen readers can follow reliably. (That is the number one, not the letter L.)

Tip

When output is long or confusing, redirect it to a file: command > output.txt, then open with notepad.exe output.txt. This is always clearer than reading raw terminal output and works with all four screen readers.

Rule 4 — When output is confusing, redirect to a file.
command > output.txt then notepad.exe output.txt. This works with all four screen readers and is always clearer than reading raw terminal output.

Rule 5 — Save everything you create.
Keep all practice files in a dedicated learning folder: mkdir -p ~/Documents/GitBash_Learning



Screen Reader Accessibility Guide for Git Bash


Target Users: NVDA, JAWS, and other screen reader users
Last Updated: 2026

This guide is used throughout the Git Bash Foundation curriculum to help screen reader users navigate and work efficiently with the terminal.

Table of Contents

  1. Getting Started with Screen Readers
  2. NVDA-Specific Tips
  3. JAWS-Specific Tips
  4. General Terminal Accessibility
  5. Working with Long Output
  6. Keyboard Shortcuts Reference
  7. Troubleshooting

Getting Started with Screen Readers

Which Screen Reader Should I Use?

Both NVDA and JAWS work well with Git Bash, but they have different strengths:

FeatureNVDAJAWS
CostFreeCommercial (paid)
InstallationSimpleComplex but thorough
Git Bash SupportExcellentExcellent
Learning CurveGentleSteeper
CustomizationGoodExtensive

Recommendation: Start with NVDA if you’re new to screen readers. Both will work for this curriculum.

Additional options: Dolphin SuperNova is a commercial screen reader/ magnifier popular in some education settings; Windows Narrator is built into Windows and useful for quick access without installing additional software. Choose based on availability and personal preference.

Before You Start

  1. Make sure your screen reader is running before opening Git Bash
  2. Open Git Bash and let your screen reader read the window title and prompt
  3. If you don’t hear anything, press Alt+Tab to cycle windows and find Git Bash
  4. Use your screen reader’s screen review features to understand the layout

What is Git Bash?

Git Bash is a terminal application for Windows that provides a Unix-style command-line experience (Bash shell). It is installed as part of Git for Windows, which is free software available at https://git-scm.com/. When you open Git Bash, you get the same bash, ls, grep, cat, and other Unix tools used on Linux and macOS - but running on your Windows computer.

NVDA-Specific Tips

NVDA is free and available from https://www.nvaccess.org/

Key Commands for Git Bash

CommandWhat It Does
NVDA+HomeRead the current line (your command or output)
NVDA+Down ArrowRead from cursor to end of screen
NVDA+Up ArrowRead from top to cursor
NVDA+Page DownRead next page
NVDA+Page UpRead previous page
NVDA+F7Open the Review Mode viewer (can scroll through text)
NVDA+Shift+Right ArrowRead next word
NVDA+Shift+Down ArrowRead entire screen
NVDA+EndJump to end of line
NVDA+HomeJump to start of line

Example: Reading Long Output

Scenario: You ran ls and it listed 50 files.

Solution with NVDA:

  1. After the command finishes, press NVDA+Home to read the current line
  2. Press NVDA+Down Arrow repeatedly to read all output
  3. Or press NVDA+F7 to open Review Mode and use arrow keys to scroll

Tip: Use ls -1 for Screen Reader Friendly Listings

By default, ls in Git Bash may display files in columns. Use ls -1 (the number one, not the letter L) to display one file per line - much easier to follow with a screen reader.

JAWS-Specific Tips

JAWS is a commercial screen reader available from https://www.freedomscientific.com/

Dolphin SuperNova

Dolphin SuperNova (commercial): https://example.com — provides speech and braille support and tightly integrated magnification. Refer to vendor docs for keyboard mappings; many users rely on review-mode features similar to NVDA/JAWS.

Windows Narrator

Windows Narrator (built-in): https://example.com — good for quick checks and lightweight usage; Narrator command keys differ by Windows version (use Narrator key + arrow keys to read). Add Narrator to your workflow when a full third-party screen reader isn’t available.

Key Commands for Git Bash

CommandWhat It Does
Insert+Down ArrowRead line by line downward
Insert+Up ArrowRead line by line upward
Insert+Page DownRead next page of text
Insert+Page UpRead previous page of text
Insert+EndJump to end of text on screen
Insert+HomeJump to start of text on screen
Insert+Ctrl+DownRead to end of screen
Insert+Ctrl+UpRead to beginning of screen
Insert+F3Open JAWS menu

Example: Reading Long Output

Scenario: You ran ls > list.txt and saved output to a file.

Solution with JAWS:

  1. Open the file: notepad list.txt
  2. In Notepad, press Insert+Ctrl+Down to hear all content
  3. Use Insert+Down Arrow to read line by line at your own pace

General Terminal Accessibility

Understanding the Git Bash Layout

The Git Bash window contains:

  1. Title bar: Window name (e.g., “MINGW64:/c/Users/YourName”)
  2. Content area: Command history and output
  3. Prompt: Where you type (e.g., YourName@COMPUTER MINGW64 ~$)

Your screen reader reads from top to bottom, but focus is at the prompt (bottom).

The Git Bash Prompt

The default Git Bash prompt looks like:

YourName@COMPUTERNAME MINGW64 ~/Documents
$
  • YourName = your Windows username
  • COMPUTERNAME = your computer’s name
  • MINGW64 = the environment type (64-bit)
  • ~/Documents = your current location
  • $ = ready for input

Note: Paths in Git Bash use forward slashes (/) and your Windows C:\Users\YourName folder appears as /c/Users/YourName or simply ~.

When you open Git Bash:

  1. Your screen reader announces the window title
  2. Then it announces the prompt line
  3. Anything before the prompt is previous output
  4. Anything after the prompt is where new output will appear

Reading Output Effectively

Strategy 1: Immediate Output (Small Amount)

  • Run a command
  • Your screen reader announces output immediately
  • This works well for short outputs (a few lines)

Strategy 2: Large Output (Many Lines)

  • Redirect to a file: command > output.txt
  • Open the file: notepad output.txt
  • Read in Notepad (easier for long text)

Strategy 3: Searching Output

  • Use grep to filter:

    ls | grep "pattern"
    
  • Only results matching “pattern” are shown

Working with Long Output

Solution 1: Redirect to a File

ls -1 > list.txt
notepad list.txt

Solution 2: Use Pagination

ls | less
  • Press Space to see next page
  • Press Q to quit
  • Note: Some screen readers struggle with less, so Solution 1 is preferred

Solution 3: Filter Output

ls | grep "\.scad"

Solution 4: Count Before Displaying

ls | wc -l

Tells you how many items there are. If the count is over 20, use the file method.

Keyboard Shortcuts Reference

All Users (Works in Git Bash Regardless of Screen Reader)

KeyAction
Up ArrowShow previous command
Down ArrowShow next command
TabAuto-complete file/folder names
Shift+TabCycle backward through completions
HomeJump to start of line
EndJump to end of line
Ctrl+AJump to start of line (alternate)
Ctrl+EJump to end of line (alternate)
Ctrl+CStop command
Ctrl+LClear screen
EnterRun command
Ctrl+RSearch command history interactively

Troubleshooting

Problem 1: “I Can’t Hear the Output After Running a Command”

  1. Redirect to file: command > output.txt then notepad output.txt
  2. Press End or Ctrl+End to go to end of text
  3. Use Up Arrow to review previous command

Problem 2: “Tab Completion Isn’t Working”

  1. Need at least one character - type cd D then Tab (not just cd then Tab)
  2. Check if item exists - use ls first to see available items
  3. Multiple matches - press Tab twice to list all options

Problem 3: “‘Command Not Found’ Error”

  1. Check spelling carefully
  2. Git Bash uses Unix commands: use ls not dir, use cat not type
  3. Verify the program is installed and in your PATH: which openscad

Problem 4: “Paths Look Weird”

Git Bash converts Windows paths to Unix style:

  • Windows: C:\Users\YourName\Documents
  • Git Bash: /c/Users/YourName/Documents or ~/Documents

Both refer to the same location. When opening files in Windows apps (like Notepad), you may need to use the Windows path format.

Problem 5: “Command Runs Forever and Won’t Stop”

Press Ctrl+C

Problem 6: “I Need to Edit My Last Command”

  1. Press Up Arrow to show previous command
  2. Use arrow keys to move through it
  3. Edit the command
  4. Press Enter to run the modified version

Pro Tips for Efficiency

1. Use ls -1 for Screen Reader Friendly Listings

ls -1

One file per line - much easier to follow with a screen reader.

2. Create Aliases for Frequently Used Commands

alias la='ls -1a'

Add this to your ~/.bashrc file to make it permanent.

3. Use Command History Effectively

history

Run a previous command by number:

!5

(Runs the 5th command in history)

Or search history interactively:

# Press Ctrl+R then type part of a previous command

4. Redirect Everything to Files for Accessibility

command-name > results.txt
notepad results.txt

5. Create a README for Yourself

echo "ls -1 means list files one per line (screen reader friendly)" > my-notes.txt
echo "cd means change directory" >> my-notes.txt
notepad my-notes.txt

For every new task:

  1. Know where you are: pwd
  2. See what’s around: ls -1
  3. Plan your next step: Think before typing
  4. Run the command: Type and press Enter
  5. Check the output: Use screen reader or redirect to file
  6. Move forward: Next command or cd to next folder

Quick Reference Card

EVERY COMMAND STARTS WITH:
1. pwd (where am I?)
2. ls -1 (what's here?)
3. cd path (go there)

LONG OUTPUT?
-> command > file.txt
-> notepad file.txt

STUCK?
-> Ctrl+C

WANT TO REPEAT?
-> Up Arrow
-> history

NEED HELP?
-> man command-name  (or: command --help)

Additional Resources


Tutorial: Git Bash Quick Start


Estimated time: 30-45 minutes

Learning Objectives

  • Launch Git Bash and identify the prompt
  • Understand and use basic path notation (~, ./, ../)
  • Use pwd, ls -1, and cd to navigate the filesystem
  • Open files in an external editor and run simple commands

Materials

  • A computer with Git Bash installed (install via https://git-scm.com/)
  • Access to a text editor (Notepad, VS Code)

Pre-Requisite Knowledge

  • Typing and basic text-editing skills
  • Familiarity with file/folder concepts and basic OS navigation
  • Basic screen-reading familiarity (if applicable)

What is Git Bash?

Git Bash is a free terminal application for Windows that provides a Bash (Unix shell) environment. It is installed as part of Git for Windows. When you open Git Bash, you can use Unix commands like ls, cat, grep, and echo - the same commands used on Linux and macOS - right on your Windows computer.

Git Bash is useful for:

  • Running CLI programs (like OpenSCAD, slicers, or 3DMake)
  • Navigating the filesystem with keyboard-only commands
  • Automating repetitive tasks with scripts
  • Accessibility: works cleanly with NVDA, JAWS, and other screen readers

What We’ll Do and Why

You’ll use Git Bash to run CLI programs, navigate the filesystem, and manipulate files - tasks that are especially efficient when using a keyboard or a screen reader.

Quick Tutorial & Core Concepts

Paths and Navigation

  • ~ - home directory (e.g., /c/Users/YourName)
  • . - current directory
  • .. - parent directory
  • ./ - current directory shortcut (used to run scripts: ./script.sh)
  • ../ - parent directory shortcut
  • Use Tab to autocomplete files and folders

Git Bash uses forward slashes (/) for paths, just like Linux. Your Windows C:\Users\YourName folder is accessible as /c/Users/YourName or simply ~.

Useful Commands (Examples)

pwd                # show current directory
ls -1              # list files, one per line (screen-reader friendly)
cd path/to/dir     # change directory
whoami             # current user

Wildcards

  • * matches zero or more characters
  • ? matches a single character

Use ls *.scad to filter by extension, for example.

Common Operations

File and Folder Manipulation

mkdir my-folder          # create folder
mkdir -p a/b/c           # create nested folders at once
cp -r src dest           # copy (use -r for directories)
mv oldname newname       # rename or move
rm file                  # remove file
rm -r folder             # remove folder and contents
touch filename.txt       # create new empty file

Input, Output, and Piping

echo 'hello' | clip      # copy to clipboard
command > output.txt     # redirect output to file
command >> output.txt    # append output to file
command > /dev/null      # discard/suppress output

Use | to pipe output and > to redirect into files.

Editing and Running Programs

notepad file.txt         # open in Notepad (Windows)
code file.txt            # open in VS Code (if in PATH)
./script.sh              # run a script in the current directory
chmod +x script.sh       # make a script executable

Screen-Reader Friendly Tips

  • Prefer ls -1 for name-only, one-per-line output.
  • Filter lists with grep: ls -1 ~/Documents | grep "\.scad$" (files only ending in .scad).
  • Redirect very long outputs to a file and open it in an editor.

Error Handling and Control

  • Abort a running command: Ctrl+C
  • View history: Up/Down arrows or history
  • Clear screen: clear (or Ctrl+L)
  • If an error is long, read the first few lines for the gist and copy short snippets into a file to examine.

Environment Variables & PATH

Environment variables configure your session. PATH tells the shell where to find executables.

echo $PATH
echo $HOME
echo $USER

To add a directory to PATH for the current session:

export PATH="$PATH:/path/to/my/tools"

To make it permanent, add that line to ~/.bashrc.

Running CLI Applications and Archives

To extract ZIP archives in Git Bash:

# Unzip a file
unzip file.zip -d destinationfolder

# Or use Windows' built-in tool (from Git Bash):
powershell.exe Expand-Archive -Path file.zip -DestinationPath folder

Aliases and Cross-Platform Notes

Git Bash provides Unix commands that work identically on Linux and macOS. This means your Git Bash skills transfer directly if you ever work on a Mac or Linux system.

Useful aliases to add to ~/.bashrc:

alias ll='ls -la'
alias la='ls -1a'
alias ..='cd ..'
alias ...='cd ../..'

Step-by-step Tasks (Hands-On)

  1. Open Git Bash; listen for the prompt and current path.
  2. Run pwd to confirm your location.
  3. Run ls -1 in your home directory and note the output.
  4. Practice cd Documents, cd ../, and cd ~ to move between folders.
  5. Create and open a file: touch example.txt && notepad example.txt (or code example.txt).

Checkpoints

  • After step 3 you should be able to state your current directory.
  • After step 5 you should be able to create and open a text file from Git Bash.

Quick Quiz (10 questions)

  1. What command prints your current directory?
  2. What does ~ represent?
  3. How do you list only names, one per line?
  4. How do you go up one directory level?
  5. How would you open notes.txt in Notepad from Git Bash?
  6. True or False: The pipe operator | sends output to a file.
  7. Explain why running a script requires chmod +x first.
  8. What is the difference between running a script with ./script.sh versus bash script.sh?
  9. Describe how you would handle a very long command output when using a screen reader.
  10. What does the PATH environment variable do, and why is it important when running programs like OpenSCAD?

Extension Problems

  1. Create a folder OpenSCADProjects in Documents and verify its contents.
  2. Create three files named a.scad, b.scad, c.scad and list them with a wildcard.
  3. Save ls -1 ~/Documents output to doclist.txt and open it.
  4. Try tab-completion in a deeply nested folder and note behavior.
  5. Capture pwd output into a file and open it: pwd > cwd.txt && notepad cwd.txt.
  6. Build an automated setup script that creates a complete project directory structure, initializes placeholder files, and generates a README.
  7. Create a Git Bash cheat sheet for your most-used commands; organize by category (navigation, files, scripting, troubleshooting).
  8. Write a non-visual tutorial for Git Bash basics; use audio descriptions and keyboard-only navigation as the primary learning method.
  9. Develop a workflow automation script: combines multiple Git Bash concepts (folders, aliases, piping) to solve a real 3D printing task.
  10. Create a Git Bash proficiency self-assessment: list all concepts covered, provide test commands for each, and reflect on what you learned.

References

Helpful Resources

Other Screen Readers

Dolphin SuperNova (commercial) and Windows Narrator (built-in) are also supported; the workflows and recommendations in this document apply to them. See https://example.com and https://example.com for vendor documentation.


Lesson Pre: Your First Terminal — Screen Reader Navigation Fundamentals


Duration: 1.5-2 hours (for screen reader users)
Prerequisites: None - this is the starting point
Accessibility Note: This lesson is designed specifically for screen reader users (NVDA, JAWS)

Important

Git Bash uses Unix/bash commands, different from Windows CMD/PowerShell

What is Git Bash?

Git Bash is a Unix/Linux shell running on Windows. It gives you bash commands (same as macOS and Linux) while staying on your Windows computer.

Why learn this?

  • Faster and more precise work (especially for 3D printing scripts and automation)
  • Essential for programming and using tools like OpenSCAD
  • Accessibility: Git Bash works perfectly with screen readers
  • Transferable: Same commands work on macOS and Linux
  • Industry-standard: Professional developers use this everywhere

Installing and Opening Git Bash

3DMake: Your First Real-World Goal

3DMake (github.com/tdeck/3dmake) is a free, accessibility-first command-line tool for designing and 3D-printing models entirely from the terminal — no mouse required. Every Git Bash skill in this curriculum directly supports a real 3DMake workflow.

Here is the end goal — one command that builds your OpenSCAD model, slices it, and sends it to the printer:

# Navigate to your project folder
cd ~/Documents/3d_projects/my_cube

# Build, slice, and print in a single command
3dm build slice print

Keep this goal in mind as you work through each lesson.

Installing and Opening Git Bash

Installation (If Not Already Installed)

  1. Download from: https://git-scm.com/download/win
  2. Run the installer
  3. Accept defaults (all options work fine)
  4. Installation takes ~5 minutes

Opening Git Bash

Method 1: Search (Easiest)

  1. Press the Windows key alone
  2. You should hear “Search”
  3. Type: Git Bash
  4. You’ll hear search results appear
  5. Press Enter to open

Method 2: From File Explorer

  1. Open File Explorer
  2. Navigate to any folder
  3. Right-click on the folder
  4. Look for “Git Bash Here”
  5. Press Enter

First Connection: Understanding the Prompt

When Git Bash opens, your screen reader will announce the window title and then the prompt.

What you’ll hear (typical example):

user@computer MINGW64 ~
$

What this means:

  • user = Your username
  • @computer = Your computer name
  • MINGW64 = Version of Git Bash
  • ~ = Your current location (home directory)
  • $ = The prompt is ready for your input

Important

Your cursor is blinking right after the $. This is where you type.

Your First Commands (Screen Reader Edition)

Command 1: “Where Am I?” - pwd

What it does: Tells you your current location

Type this:

pwd

Press Enter

What you’ll hear: Your screen reader will announce the current path, something like:

/c/Users/YourName

Understanding paths in Git Bash:

  • Paths use forward slashes: /c/Users/YourName/Documents
  • /c/ means the C: drive (Windows drive)
  • This is Unix-style, same as macOS and Linux
  • Think of it like folders inside folders: /c/ (main drive) -> Users -> YourName -> Documents

Command 2: “What’s Here?” - ls

What it does: Lists all files and folders in your current location

Type this:

ls

Press Enter

What you’ll hear: Your screen reader will announce a list of file and folder names, one per line. Perfect for screen readers!

Command 3: “Go There” - cd Documents

What it does: Changes your location (navigates to a folder)

Type this:

cd Documents

Press Enter

What you’ll hear: The prompt changes to show your new location. You might hear something like:

user@computer MINGW64 ~/Documents
$

Practice navigation:

  1. Run pwd to confirm you’re in Documents
  2. Run ls to see what files are in Documents
  3. Try going back: cd .. (the .. means “go up one level”)
  4. Run pwd again to confirm
  5. Go back to Documents: cd Documents

Creating and Viewing Files

Create a Simple File

Type this:

echo "Hello, Git Bash!" > hello.txt

What this does:

  • echo sends text to the screen (or file)
  • "Hello, Git Bash!" is the text
  • > redirects it to a file called hello.txt

Read the File Back

Type this:

cat hello.txt

What you’ll hear: Your screen reader announces:

Hello, Git Bash!

Open and Edit the File

Type this:

notepad.exe hello.txt

This opens the file in Notepad where you can edit it with your screen reader.

Essential Keyboard Shortcuts

These work in Git Bash and are crucial for screen reader users:

Key CombinationWhat It Does
Up ArrowShows your previous command (press again to go further back)
Down ArrowShows your next command (if you went back)
TabAuto-completes folder/file names
Ctrl+CStops a running command
Ctrl+LClears the screen
Ctrl+AGo to beginning of line
Ctrl+EGo to end of line
EnterRuns the command

Screen reader tip: These all work perfectly with your screen reader. Try them!

Screen Reader-Specific Tips

NVDA Users

  1. Reading Command Output:

    • Use NVDA+Home to read the current line
    • Use NVDA+Down Arrow to read to the end of the screen
    • Use NVDA+Page Down to read the next page
  2. Reviewing Text:

    • Use NVDA+Shift+Page Up to review text above

JAWS Users

  1. Reading Output:

    • Use Insert+Down Arrow to read line-by-line
    • Use Insert+Page Down to read by page
    • Use Insert+End to jump to the end of text
  2. Reading All Text:

    • Use Insert+Down Arrow repeatedly
    • Or use Insert+Ctrl+Down to read to the end

Common Issue: “I Can’t Hear the Output”

Problem: You run a command but don’t hear the output

Solutions:

  1. Make sure your cursor is at the prompt (try pressing End or Ctrl+E)
  2. Use Up Arrow to go back to your previous command and review it
  3. Try redirecting to a file: command > output.txt then open the file
  4. In NVDA: Try pressing NVDA+F7 to open the Review Mode viewer

Practice Exercises

Complete these in order. Take your time with each one:

Exercise 1: Basic Navigation

  1. Open Git Bash
  2. Run pwd and note your location
  3. Run ls and listen to what’s there
  4. Try cd Documents or another folder
  5. Run pwd to confirm your new location
  6. Run ls in this new location

Goal: You should be comfortable knowing where you are and what’s around you

Exercise 2: Using Tab Completion

  1. In your home directory, type cd D (just the letter D)
  2. Press Tab
  3. Git Bash should auto-complete to a folder starting with D
  4. Repeat with other folder names
  5. Try typing a longer name: cd Down and Tab

Goal: Tab completion should feel natural

Exercise 3: Creating and Viewing Files

  1. Create a file: echo "Test content" > test.txt
  2. View it: cat test.txt
  3. Create another: echo "Line 2" > another.txt
  4. List both: ls *.txt

Goal: You understand create, view, and list operations

Exercise 4: Going Up Levels

  1. Navigate into several folders: cd Documents, then cd folder1, etc.
  2. From deep inside, use cd .. multiple times to go back up
  3. After each cd .., run pwd to confirm your location

Goal: You understand relative navigation with ..

Exercise 5: Redirecting Output

  1. Create a list: ls > directorylist.txt
  2. Open it: notepad.exe directorylist.txt
  3. Read it with your screen reader
  4. Close Notepad
  5. Verify the file exists: ls | grep directory

Goal: You can save long outputs to files for easier reading

Checkpoint Questions

After completing this lesson, you should be able to answer:

  1. What does pwd do?
  2. What does ls do?
  3. Why do we use ls for listings?
  4. What path are you in right now?
  5. How do you navigate to a new folder?
  6. How do you go up one level?
  7. What’s the Tab key for?
  8. What does echo "text" > file.txt do?
  9. How do you read a file back?
  10. How do you stop a command that’s running?

You should be able to answer all 10 with confidence before moving to Bash Lesson 0.

Common Questions

Q: Is Git Bash the same as Command Prompt or PowerShell? A: No. Git Bash uses Unix/bash commands. CMD and PowerShell use Windows commands. This curriculum teaches bash (Unix) style.

Q: Why is my screen reader not reading the output? A: This is common. Use command > file.txt to save output to a file, then open it with Notepad for reliable reading.

Q: What if I type something wrong? A: Just press Enter and you’ll see an error message. Type the correct command on the next line. No harm done!

Q: How do I get help with a command? A: Type man command-name (we’ll cover this in Bash Lesson 0)

Q: Why do paths look different in Git Bash? A: Git Bash uses Unix-style paths with forward slashes, not Windows backslashes. Don’t worry - you’ll get used to it quickly.

Path Comparison: Windows vs Git Bash

StyleExampleWhere Used
WindowsC:\Users\Name\DocumentsCMD, PowerShell, Windows Explorer
Git Bash/c/Users/Name/DocumentsGit Bash, macOS Terminal, Linux

In Git Bash:

  • C:\ becomes /c/
  • Backslashes \ become forward slashes /
  • Otherwise identical

Next Steps

Once you’re comfortable with these basics:

  • Move to Bash Lesson 0: Getting Started for deeper path understanding
  • Then continue through Bash Lesson 1 through Bash Lesson 5 for full terminal mastery

Resources

Troubleshooting

IssueSolution
Git Bash won’t openMake sure it’s installed; search for “Git Bash” in Start menu
Can’t hear the outputTry redirecting to a file: command > output.txt
Tab completion not workingMake sure you typed at least one character before pressing Tab
Command not foundMake sure you spelled it correctly; try man for available commands
Stuck in a commandPress Ctrl+C to stop it

Still stuck? The checkpoint questions and exercises are your best teacher. Work through them multiple times until comfortable.

Other Screen Readers

Dolphin SuperNova (commercial) and Windows Narrator (built-in) are also supported; the workflows and recommendations in this document apply to them. See https://yourdolphin.com/supernova/ and https://support.microsoft.com/narrator for vendor documentation.


Lesson 0: Getting Started — Layout, Paths, and the Shell


Estimated time: 20-30 minutes

Learning Objectives

  • Launch Git Bash and locate the prompt
  • Understand Unix-style path notation and shortcuts (~, ./, ../)
  • Use tab completion to navigate quickly

Materials

  • Computer with Git Bash installed
  • Editor (Notepad/VS Code)

Step-by-step Tasks

  1. Open Git Bash and note the prompt (it includes the current path).
  2. Run pwd and say or note the printed path.
  3. Use ls to list names in your home directory.
  4. Practice cd Documents, cd ../ and cd ~ until comfortable.
  5. Try tab-completion: type cd ~/D and press Tab.

Checkpoints

  • Confirm you can state your current path and move to Documents.

Quiz - Lesson GitBash.0

3DMake Quick-Start: Your First Real Project

You now know enough Git Bash to set up a real 3DMake project. Do this now — it is the fastest path to a printed object.

Step 1 — Download and run the 3DMake setup wizard:

# Go to your Downloads folder (where you extracted 3dmake)
cd ~/Downloads/3dmake

# Run the guided setup (answer the questions about your printer)
./3dm setup

Step 2 — Create your first project:

# Create a folder for all your 3D projects and initialize the first one
mkdir -p ~/Documents/3d_projects/my_cube
cd ~/Documents/3d_projects/my_cube
3dm new

Step 3 — Confirm the project structure:

# You should see three items: src/, build/, and 3dmake.toml
ls -1

You just used mkdir, cd, and ls -1 on a real project. You are ready to print.

Checkpoints

  • Confirm you can state your current path and move to Documents.

Quiz - Lesson GitBash.0

  1. What is a path?
  2. What does ~ mean?
  3. How do you autocomplete a path?
  4. How do you go up one directory?
  5. What command lists file names?

Note

Git Bash uses forward slashes (/) in paths, not Windows-style backslashes (\). For example: /c/Users/YourName/Documents. This is the Unix convention and transfers directly to macOS and Linux.

  1. True or False: Git Bash uses backslashes (\) in paths like Windows CMD.
  2. Explain the difference between an absolute path and a relative path.
  3. If you are in /c/Users/YourName/Documents and you type cd ../, where do you end up?
  4. What happens when you press Tab while typing a folder name in Git Bash?
  5. Describe a practical reason why understanding paths is important for a 3D printing workflow.
  6. What does ./ mean in a path, and when would you use it?

Note

When a folder name contains spaces, always wrap the full path in double quotes: cd "My Projects". Without quotes, the shell interprets the space as a separator between two separate arguments.

  1. If a folder path contains spaces (e.g., My Projects), how do you navigate to it with cd?
  2. Explain what the prompt YourName@COMPUTER MINGW64 ~/Documents $ tells you about your current state.
  3. How would you navigate to your home directory from any location using a single command?
  4. What is the advantage of using relative paths (like ../) versus absolute paths in automation scripts?

Extension Problems

  1. Create a nested folder and practice cd into it by typing partial names and using Tab.
  2. Use ls -la to list all files including hidden ones in a folder.
  3. Save pwd output to a file and open it in Notepad.
  4. Try cd into a folder whose name contains spaces; observe how quotes are handled.
  5. Create a short note file and open it from Git Bash.
  6. Build a folder structure that mirrors your project organization; navigate to each level and document the path.
  7. Create a script that prints your current path and the total number of files in it; run it from different locations.
  8. Investigate special paths (e.g., $HOME, $USER); write down what each contains and when you’d use them.
  9. Compare absolute vs. relative paths by navigating to the same folder using each method; explain which is easier for automation.
  10. Create a bash function that changes to a frequently-used folder and lists its contents in one command; test it from different starting locations.
  11. Navigate to three different locations and at each one note the prompt, the path from pwd, and verify you understand what each shows.
  12. Create a complex folder tree (at least 5 levels deep) and navigate it using only relative paths; verify your location at each step.
  13. Document all shortcuts you know (~, ./, ../, $HOME) and demonstrate each one works as expected.
  14. Write a guide for a peer on how to understand the Git Bash prompt and path notation without using GUI file explorer.
  15. Create a troubleshooting flowchart: if someone says “I don’t know where I am,” what commands do you give them to find out?

References

Helpful Resources


Lesson 1: Navigation — Moving Around Your File System


Duration: 1 class period Prerequisite: Bash Lesson 0 (Getting Started)

Learning Objectives

By the end of this lesson, you will be able to:

  • Use pwd to print your current location
  • Use cd to move between directories
  • Use ls (and its flags) to list files and folders
  • Use wildcards * and ? to filter listings
  • Navigate relative vs. absolute paths
  • Search for files by name and extension

Materials

  • Git Bash
  • Text editor (Notepad or VS Code)

Commands Covered in This Lesson

CommandWhat It Does
pwdPrint Working Directory - shows where you are
cd pathChange Directory - move to a new location
lsList - shows files and folders in current location
ls -1List names only, one per line (screen reader friendly)
ls -1 -FList names with type indicators (/ for directories)
ls *.extensionList files matching a pattern

pwd - Where Am I?

Type pwd and press Enter. Git Bash prints the full path to your current location.

pwd
# Output: /c/Users/YourName

When to use: Always run this if you’re unsure of your current location.


cd - Changing Directories

cd stands for “change directory.”

# Go to Documents
cd Documents

# Go up one level to parent directory
cd ..

# Go to root of file system
cd /

# Go to home directory
cd ~

# Go to a specific path
cd /c/Users/YourName/Documents/3D_Projects

# Go to previous directory
cd -

ls - Listing Files and Folders

Use ls -1 for screen reader compatibility — names only, one per line.

# List all files and folders (names only, one per line)
ls -1

# List only files (no hidden, no directories)
ls -1 -p | grep -v /

# List only directories
ls -1 -d */

Wildcards - Finding Files by Pattern

Wildcards help you find files without typing the full name.

* (asterisk) matches any number of characters:

# List all .scad files
ls *.scad

# List all files starting with "part"
ls part*

# List all files ending with "_final"
ls *_final*

? (question mark) matches exactly one character:

# Find files like model1.scad, model2.scad (but not model12.scad)
ls model?.scad

Step-by-step Practice

  1. Run pwd and confirm your location
  2. Move to Documents: cd Documents

3DMake in Practice: Navigating a Project

Navigation commands are exactly what you need to explore and manage 3DMake projects:

# Go to your project root
cd ~/Documents/3d_projects/my_cube

# See the project layout: src/, build/, 3dmake.toml
ls -1

# Enter the source folder where your .scad model files live
cd src
ls -1

# Open the main model in your text editor
3dm edit-model

# Go back to project root, then check build output
cd ..
cd build
ls -1 *.stl

# Return to project root
cd ..

# Use wildcards to find all projects with "cube" in the name
ls -1 ~/Documents/3d_projects/*cube*

Tab completion makes navigation fast: type cd ~/Doc and press Tab.


Step-by-step Practice

  1. Run pwd and confirm your location
  2. Move to Documents: cd Documents
  3. Confirm you moved: pwd
  4. List files and folders: ls -1
  5. List only files: ls -1 -p | grep -v /
  6. Go back up: cd ..
  7. Search for files: ls *.txt

Checkpoints

After this lesson, you should be able to:

  • Navigate to any folder using cd
  • Confirm your location with pwd
  • List files and folders with ls -1
  • Use wildcards to find files by pattern
  • Move between absolute and relative paths confidently

Quiz - Lesson GitBash.1

  1. What does pwd show?
  2. How do you list directories only with ls?
  3. What wildcard matches any number of characters?
  4. How do you list files with the .scad extension?
  5. Give an example of an absolute path and a relative path.
  6. True or False: The * wildcard matches exactly one character.
  7. Explain the difference between ls -1 and ls -1 -d */.
  8. Write a command that would list all .txt files in your Documents folder using a wildcard.
  9. How would you search for files containing “part” in their name across multiple files?
  10. Describe a practical scenario where using wildcards saves time in a 3D printing workflow.
  11. What happens when you use ls model?.scad versus ls model*.scad?
  12. How would you navigate to a folder whose name contains both spaces and special characters?
  13. If you’re in ~/Documents/Projects/3D and you want to go to ~/Documents/Resources, what command would you use?
  14. Write a command sequence that navigates to the Downloads folder, lists only files, then returns to home.
  15. Explain the purpose of using ls -1 specifically in a screen reader context.

Extension Problems

  1. Write a one-line command that lists .scad files and saves to scad_list.txt.
  2. Use ls -1 ~/Documents | less to page through long listings.
  3. Combine ls with grep to search for a filename pattern.
  4. Create a shortcut alias in the session for a long path and test it.
  5. Practice tab-completion in a directory with many similarly named files.
  6. Build a bash script that recursively lists all .scad and .stl files in a directory tree; save the results to a file.
  7. Compare the output of ls, ls -1, ls -la, and ls -1 -d */ to understand the flags; document what each command does.
  8. Create a filtering command that displays only files modified in the last 7 days; test it on your documents folder.
  9. Write a non-visual guide to Git Bash navigation; include descriptions of common patterns and how to verify directory contents audibly.
  10. Develop a navigation workflow for a typical 3D printing project: move between CAD, slicing, and print-log folders efficiently; document the commands.
  11. Create a complex wildcard search: find all files in a folder and subfolders that match multiple patterns (e.g., *_v1.* or *_final.*).
  12. Build a script that navigates through a folder tree, counts files at each level, and reports the structure.
  13. Document the output differences between ls, ls -1, ls -la, and ls -1 -d */; explain when to use each.
  14. Create a navigation “cheat sheet” as a bash script that prints common paths and how to navigate to them.
  15. Design a project folder structure on your computer, document each path, then create a script that validates all folders exist.

References

Helpful Resources


Lesson 2: File and Folder Manipulation


Estimated time: 30-45 minutes

Learning Objectives

  • Create, copy, move, and delete files and folders from Git Bash
  • Use touch, mkdir, cp, mv, rm, and rmdir safely
  • Understand when operations are permanent and how to confirm results

Materials

  • Git Bash
  • Small practice folder for exercises

Step-by-step Tasks

  1. Create a practice directory: mkdir ~/Documents/GitBash_Practice and cd into it.
  2. Create two files: touch file1.txt and touch file2.txt.
  3. Copy file1.txt to file1_backup.txt with cp and confirm with ls -1.
  4. Rename file2.txt to notes.txt using mv and confirm.
  5. Delete file1.txt with rm and verify the backup remains.

Checkpoints

  • After step 3 you should see both the original and the backup file.

3DMake in Practice: Organizing Your Projects

File management commands are essential for 3DMake project organization:

# Create a new project from scratch
mkdir -p ~/Documents/3d_projects/bottle_cap
cd ~/Documents/3d_projects/bottle_cap
3dm new

# Back up a working project before making big changes
cd ~/Documents/3d_projects
cp -r bottle_cap bottle_cap_backup

# Rename the main model file to something more specific
cd bottle_cap/src
mv main.scad bottle_cap.scad

# List only .scad files to confirm the rename
ls -1 *.scad

# Delete a draft STL you no longer need
rm ~/Documents/3d_projects/bottle_cap/build/draft.stl

# Build the renamed model (using the -m flag to specify the name)
cd ~/Documents/3d_projects/bottle_cap
3dm build -m bottle_cap

# See the fresh output in the build folder
ls -1 build/

Checkpoints

  • After step 3 you should see both the original and the backup file.

Quiz - Lesson GitBash.2

  1. How do you create an empty file from Git Bash?
  2. What command copies a file?
  3. How do you rename a file?
  4. What does rm -r do?

Warning

rm permanently deletes files with no undo and no Recycle Bin. There is no recovery from Git Bash. Always run ls -1 first to confirm exactly what you’re targeting, especially when using wildcards.

  1. Why is rm potentially dangerous?
  2. True or False: cp requires the -r flag to copy both files and folders.
  3. Explain the difference between rm and rmdir.
  4. If you delete a file with rm, can you recover it from Git Bash?
  5. Write a command that would copy an entire folder and all its contents to a new location.
  6. Describe a practical safety check you would perform before running rm -r on a folder.
  7. What happens if you cp a file to a destination where a file with the same name already exists? How would you handle this safely?
  8. Compare mv old_name.txt new_name.txt vs mv old_name.txt ~/Documents/new_name.txt. What is the key difference?
  9. Design a workflow to safely delete 50 files matching the pattern *.bak from a folder containing 500 files. What commands and verifications would you use?
  10. Explain how you could back up all .scad files from a project folder into a timestamped backup folder in one command.
  11. When organizing a 3D printing project, you need to move completed designs to an archive folder and delete failed prototypes. How would you structure this as a safe, auditable process?

Extension Problems

  1. Create a folder tree and copy it to a new location with cp -r.
  2. Write a one-line command that creates three files named a, b, c and lists them.
  3. Move a file into a new folder and confirm the move.
  4. Use wildcards to delete files matching a pattern in a safe test folder.
  5. Export a listing of the practice folder to practice_listing.txt.
  6. Create a backup shell script that copies all .scad files from your project folder to a backup folder with timestamp naming.
  7. Build a safe deletion workflow: list files matching a pattern, verify count, then delete with confirmation; document the steps.
  8. Write a bash script that organizes files by extension into subfolders; test it on a sample folder tree.
  9. Create a file operation audit trail: log all copy, move, and delete operations to a text file for review.
  10. Develop a project template generator: a bash script that creates a standard folder structure for a new 3D printing project with essential subfolders.
  11. Implement a file conflict handler: write a bash script that handles cases where cp would overwrite an existing file by renaming the existing file with a timestamp before copying.
  12. Create a batch rename operation: use a script to rename all files in a folder from old_prefix_* to new_prefix_*; test with actual files and verify the results.
  13. Build a folder comparison tool: list all files in two folders and identify which files exist in one but not the other; output to a report.
  14. Write a destructive operation validator: before executing rm -r, create a script that lists exactly what will be deleted, shows file counts by type, and requires explicit user confirmation to proceed.
  15. Design a complete project lifecycle workflow: create folders for active projects, completed designs, and archive; include move operations between folders, backup steps, and verification that all files arrive intact.

References

Helpful Resources


Lesson 3: Input, Output, and Piping


Duration: 1 class period Prerequisite: Bash Lesson 2 (File and Folder Manipulation)


Learning Objectives

By the end of this lesson, you will be able to:

  • Use echo to print text to the screen
  • Use cat to read file contents
  • Use > to redirect output into a file
  • Use | (pipe) to send one command’s output to another
  • Copy output to the clipboard with clip
  • Open files with a text editor from the command line

Commands Covered

CommandWhat It Does
echo "text"Print text to the screen
cat filenamePrint the contents of a file
> filenameRedirect output into a file (overwrites)
>> filenameAppend output to a file (adds to end)
|Pipe - send output from one command to the next
clipCopy piped input to the Windows clipboard (Git Bash)
notepad.exe filenameOpen a file in Notepad

echo - Printing Text

echo prints text to the screen. It is useful for testing, for writing text into files, and for understanding how piping works.

echo "Hello, World"
echo "This is a test"

cat - Reading Files

cat prints the contents of a file to the screen.

# Read a text file
cat ~/Documents/notes.txt

# Read an OpenSCAD file
cat ~/Documents/OpenSCAD_Projects/project0.scad

With a long file, use cat filename | less to read it page by page (press Space to advance, Q to quit).


> - Redirecting Output to a File

The > symbol redirects output from the screen into a file instead.

# Create a file with a single line
echo "Author: Your Name" > header.txt

# Confirm the file was created and has content
cat header.txt

Warning: > overwrites the file if it already exists. Use >> to append instead:

echo "Date: 2025" >> header.txt
echo "Project: Floor Marker" >> header.txt
cat header.txt

| - Piping

The pipe symbol | sends the output of one command to the input of the next. This lets you chain commands together.

# List files and send the list to clip (copies to clipboard)
ls -1 | clip
## 3DMake in Practice: Capturing Build Output

Piping and redirection are essential for working with 3DMake's output accessibly:

```bash
# Build and save the full log to a file so you can read it
3dm build > build_log.txt
cat build_log.txt

# Build and slice, keeping only lines with errors or warnings
3dm build slice 2>&1 | grep -i "error\|warning"

# List all STL files produced so far
ls -1 build/*.stl

# Get a list of available printer profiles and save for reference
3dm list-profiles > profiles.txt
cat profiles.txt

# Get a list of material overlays (PLA, PETG, supports, etc.)
3dm list-overlays > overlays.txt
cat overlays.txt

# Get an AI description of your model, then copy to clipboard
3dm info > model_description.txt
cat model_description.txt | clip
# List files and send the list to clip (copies to clipboard)
ls -1 | clip

# Now paste with Ctrl + V anywhere
# Search within a file's contents using grep
cat project0.scad | grep "cube"

clip - Copying to Clipboard

clip takes whatever is piped to it and puts it on the Windows clipboard.

# Copy your current directory path to the clipboard
pwd | clip

# Copy a file listing to clipboard
ls -1 | clip

# Copy the contents of a file to clipboard
cat notes.txt | clip

After any of these, press Ctrl + V in any application to paste.


Opening Files in Notepad

# Open a file in Notepad
notepad.exe ~/Documents/notes.txt

# Open a .scad file
notepad.exe ~/Documents/OpenSCAD_Projects/project0.scad

# Create a new file and open it
touch new_notes.txt
notepad.exe new_notes.txt

Step-by-step Tasks

  1. Create practice.txt with three lines using echo and >/>>.
  2. Read the file with cat practice.txt.
  3. Pipe the file into grep to search for a word.
  4. Copy the file contents to clipboard with cat practice.txt | clip.
  5. Redirect ls -1 into list.txt and open it in Notepad.

Checkpoints

  • After step 3 you should be able to find a keyword using piping.

Quiz - Lesson GitBash.3

  1. What is the difference between > and >>?
  2. What does the pipe | do?
  3. How do you copy output to the clipboard?
  4. How would you page through long output?
  5. How do you suppress output (send it to /dev/null)?
  6. True or False: The pipe operator | connects the output of one command to the input of another.
  7. Explain why redirecting output to a file is useful for screen reader users.
  8. Write a command that would search for the word “sphere” in all .scad files in a directory.
  9. How would you count the number of lines in a file using bash piping?
  10. Describe a practical scenario in 3D printing where you would pipe or redirect command output.
  11. What would be the difference in output between echo "test" > file.txt (run twice) vs echo "test" >> file.txt (run twice)? Show the expected file contents.
  12. Design a three-step piping chain: read a file, filter for specific content, and save the results; explain what each pipe does.
  13. You have a 500-line .scad file and need to find all instances of sphere() and count them. Write the command.
  14. Explain how clip is particularly valuable for screen reader users when working with file paths or long output strings.
  15. Describe how you would use pipes and redirection to create a timestamped backup report of all .stl files in a 3D printing project folder.

Extension Problems

  1. Use piping to count lines in a file (hint: cat file.txt | wc -l).
  2. Save a long ls -1 output and search it with grep.
  3. Chain multiple pipes to filter and then save results.
  4. Practice copying different command outputs to clipboard and pasting.
  5. Create a small bash script that generates a report (counts of files by extension).
  6. Build a data processing pipeline: read a text file, filter rows, and export results; document each step.
  7. Write a script that pipes directory listing to count occurrences of each file extension; create a summary report.
  8. Create a log analysis command: read a log file, filter for errors, and save matching lines to a separate error log.
  9. Design a piping workflow for 3D printing file management: find .stl files, extract their names, and generate a report.
  10. Develop a reusable piping function library: create bash functions for common filtering, sorting, and reporting patterns; test each with different inputs.
  11. Build a complex filter pipeline: read a .scad file, extract lines containing specific geometry commands, count each type, and output a summary to both screen and file.
  12. Create an interactive filtering tool: build a bash script that accepts a search term, pipes through multiple filters, and displays paginated results.
  13. Develop a performance analysis tool: use piping to combine file listing, metadata extraction, and statistical reporting; export results to a dated report file.
  14. Implement a comprehensive error-handling pipeline: read output, catch errors, log them separately, and generate a summary of successes vs failures.
  15. Design and execute a real-world project backup workflow: use piping to verify file existence, count files by type, generate a backup manifest, and create audit logs — all in one integrated command pipeline.

References

Helpful Resources


Lesson 4: Environment Variables, PATH, and Aliases


Estimated time: 30-45 minutes

Learning Objectives

  • Read environment variables with $VARNAME
  • Inspect and verify programs in the PATH
  • Create temporary aliases and understand making them persistent via .bashrc

Materials

  • Git Bash (with rights to edit .bashrc)

Step-by-step Tasks

  1. Show your username and home path with echo $USER and echo $HOME.
  2. Inspect echo $PATH and identify whether openscad or code would be found.
  3. Run which openscad and note the result.
  4. Create a temporary alias: alias preview='openscad' and test preview myfile.scad.
  5. Open your profile (notepad.exe ~/.bashrc) and add the alias line to make it persistent.

Checkpoints

  • After step 3 you can determine whether a program will be found by PATH.

Quiz - Lesson GitBash.4

3DMake in Practice: Aliases in .bashrc

Bash aliases make your 3DMake workflow much faster:

# Quick alias to jump to your 3D projects folder
alias 3dp='cd ~/Documents/3d_projects'

# Full build-slice-print pipeline in one word
alias 3dprint='3dm build slice print'

# Build and then get an AI description of the model
alias 3dinfo='3dm build && 3dm info'

# Make sure 3dm is in your PATH (add to .bashrc if needed)
echo 'export PATH="$PATH:$HOME/Downloads/3dmake"' >> ~/.bashrc

# Persist all three aliases in .bashrc
echo "alias 3dp='cd ~/Documents/3d_projects'" >> ~/.bashrc
echo "alias 3dprint='3dm build slice print'" >> ~/.bashrc
echo "alias 3dinfo='3dm build && 3dm info'" >> ~/.bashrc

# Reload .bashrc immediately without restarting
source ~/.bashrc

# Now use them:
3dp         # jump to your 3D projects folder
3dprint     # run the full pipeline
3dinfo      # build and describe the model

Checkpoints

  • After step 3 you can determine whether a program will be found by PATH.

Quiz - Lesson GitBash.4

  1. How do you print an environment variable?
  2. What is the purpose of PATH?
  3. How do you check whether openscad is available?
  4. How do you create a temporary alias?
  5. Where would you make an alias permanent?
  6. True or False: Environment variables in bash are case-sensitive.
  7. Explain why having a program in your PATH is useful compared to always using its full file path.
  8. Write a command that would create an alias called slicer for the OpenSCAD executable.
  9. What file would you edit to make an alias persist across Git Bash sessions?
  10. Describe a practical benefit of using the $TMPDIR or /tmp directory for temporary files in a 3D printing workflow.
  11. You have a custom script at ~/scripts/backup_models.sh that you want to run from anywhere as backup-now. What steps would you take to make this work?
  12. Explain the difference between setting an environment variable in the current session with export vs. adding it to .bashrc for permanence.
  13. Design a .bashrc strategy for managing multiple 3D printing projects, each with different tool paths and directories; show how to structure environment variables for each.
  14. If a program is not found by which, what are the possible reasons, and how would you troubleshoot?
  15. Describe how you would verify that your .bashrc is loading correctly and how to debug issues if aliases or environment variables don’t appear after restarting Git Bash.

Extension Problems

  1. Add a folder to PATH for a test program (describe steps; do not change system PATH without admin).
  2. Create a short .bashrc snippet that sets two aliases and test re-opening Git Bash.
  3. Use which to list the path for several common programs.
  4. Explore $TMPDIR or /tmp and create a file there.
  5. Save a copy of your current PATH to a text file and examine it in your editor.
  6. Create a .bashrc script that loads custom aliases and environment variables for your 3D printing workflow; test it in a new session.
  7. Build a “project profile” that sets environment variables for CAD, slicing, and print directories; switch between profiles for different projects.
  8. Write a script that audits your current environment variables and creates a summary report of what’s set and why.
  9. Design a custom alias system for common 3D printing commands; document the aliases and their purposes.
  10. Create a profile migration guide: document how to export and import your .bashrc across machines for consistent workflows.
  11. Implement a safe PATH modification script: create a utility that allows you to add/remove directories from PATH for the current session only; show how to make it permanent in .bashrc.
  12. Build a comprehensive .bashrc framework with modular sourcing: create separate .sh files for aliases, environment variables, and functions; have your main .bashrc source all of them.
  13. Develop an environment validation tool: write a bash script that checks whether all required programs (OpenSCAD, slicers, etc.) are accessible via PATH; report findings and suggest fixes.
  14. Create a project-switching alias system: design a function that changes all environment variables and aliases based on the current project; test switching between multiple projects.
  15. Build a .bashrc troubleshooting guide: create a script that exports your current environment state (variables, aliases, PATH) to a timestamped file, allowing you to compare states before and after changes.

References

Helpful Resources


Lesson 5: Filling in the Gaps — Shell Profiles, History, and Useful Tricks


Estimated time: 30-45 minutes

Learning Objectives

  • Use history and abort commands (history, Ctrl+R, Ctrl+C)
  • Inspect and edit your .bashrc profile for persistent settings
  • Run programs by full path using ./ or absolute paths
  • Handle common screen reader edge cases when using the terminal

Materials

  • Git Bash and an editor (Notepad/VS Code)

Step-by-step Tasks

  1. Run several simple commands (e.g., pwd, ls -1, echo hi) then run history to view them.
  2. Use !<n> to re-run a previous command by its history number (replace <n> with a history number).
  3. Practice aborting a long-running command with Ctrl + C (for example, ping google.com).
  4. Open your profile: notepad.exe ~/.bashrc; if it doesn’t exist, create it: touch ~/.bashrc.
  5. Add a persistent alias line to your profile (example: alias preview='openscad'), save, and run source ~/.bashrc or reopen Git Bash to verify.

Checkpoints

  • After step 2 you can re-run a recent command by history number.
  • After step 5 your alias should persist across sessions.

Quiz - Lesson GitBash.5

  1. How do you view the command history in Git Bash?
  2. Which key combination aborts a running command?
  3. What does echo $BASH_VERSION show?
  4. How does ./ help run scripts and executables in the current directory?
  5. What is one strategy if terminal output stops being announced by your screen reader?
  6. True or False: Using Ctrl+C permanently deletes any files created by the command you abort.
  7. Explain the difference between history and Ctrl+R (reverse history search) in Git Bash.
  8. If you add an alias to .bashrc but it doesn’t take effect after opening a new Git Bash window, what should you verify?
  9. Write a command that would run a script at the path ~/scripts/openscad_runner.sh directly.
  10. Describe a practical workflow scenario where having keyboard shortcuts (aliases) in your .bashrc would save time.
  11. Explain how to re-run the 5th command from your history using !5, and what would happen if that command had file operations (creates/deletes).
  12. Design a .bashrc initialization strategy that separates utilities for different projects; explain how you would switch between them.
  13. Walk through a troubleshooting workflow: your screen reader stops announcing output after running a long command. What steps would you take to diagnose and resolve the issue?
  14. Create a safety checkpoint system: before any destructive operation (mass delete, overwrite), how would you use .bashrc functions and history to verify the command is correct?
  15. Develop a comprehensive capstone scenario: integrate everything from Bash Lesson 0 through Bash Lesson 5 (navigation, file operations, piping, environment setup, history) to design an automated 3D printing project workflow with error handling and logging.

Extension Problems

  1. Add an alias and an environment variable change to your .bashrc and document the behavior after reopening Git Bash.
  2. Create a short bash script that automates creating a project folder and an initial .scad file.
  3. Experiment with running OpenSCAD by full path using ./ and by placing it in PATH; compare results.
  4. Practice redirecting man ls output to a file and reading it in Notepad for screen reader clarity.
  5. Document three screen reader troubleshooting steps you used and when they helped.
  6. Build a comprehensive .bashrc that includes aliases, environment variables, and helper functions for your 3D printing workflow.
  7. Create a bash script that troubleshoots common Git Bash issues (module loading, permission errors, command not found); test at least three scenarios.
  8. Write a bash function that coordinates multiple tasks: creates a project folder, starts OpenSCAD, and opens a notes file.
  9. Design a screen-reader accessibility guide for Git Bash: document commands, outputs, and accessible navigation patterns.
  10. Develop an advanced Git Bash workflow: implement error handling, logging, and confirmation prompts for risky operations.
  11. Implement an “undo” system using history: create a function that logs destructive commands (rm, mv, cp) and allows you to review the last operation.
  12. Build a .bashrc debugger: create a script that compares two Git Bash sessions’ environment states (variables, aliases, functions) to identify what loaded/failed to load.
  13. Develop a multi-project profile manager: design a system where you can switch entire environments (paths, aliases, variables) for different 3D printing projects by running a single command.
  14. Create a comprehensive accessibility analyzer: write a bash script that tests whether key Git Bash commands produce screen-reader-friendly output; document workarounds for commands that don’t.
  15. Design a complete capstone project: build an integrated automation suite that manages a 3D printing workflow (project setup, file organization, CAD/slicing tool automation, output logging, error recovery, and audit trails) with full error handling and documentation.

References

Helpful Resources


Lesson 6: Advanced Techniques — Shell Scripts, Functions, and Professional Workflows


Duration: 4-4.5 hours (for screen reader users) Prerequisites: Complete Bash Lesson 0 through Bash Lesson 5 Skill Level: Advanced intermediate

3DMake in Practice: Automating Your Print Workflow

Use a shell script to fully automate a 3DMake workflow across multiple projects:

#!/bin/bash
# batch_print.sh - build and print every 3DMake project in a folder

PROJECTS_DIR="$HOME/Documents/3d_projects"

for project in "$PROJECTS_DIR"/*/; do
    name=$(basename "$project")
    echo "Processing: $name"
    cd "$project"

    if 3dm build slice > build_log.txt 2>&1; then
        echo "  OK - sending to printer"
        3dm print
    else
        echo "  FAILED - check build_log.txt"
        cat build_log.txt
    fi
done

echo "Batch complete."

Tip

Save as batch_print.sh, run chmod +x batch_print.sh once to make it executable, then run with ./batch_print.sh. If you forget chmod +x you’ll get “Permission denied” — just run the chmod command and try again.

Save as batch_print.sh, make executable with chmod +x batch_print.sh, then run with ./batch_print.sh. This script uses loops, conditionals, and redirection — all from this lesson.

This lesson extends Git Bash skills to professional-level workflows. You’ll learn to automate complex tasks, write reusable shell scripts, and integrate tools for 3D printing workflows.


Learning Objectives

By the end of this lesson, you will be able to:

  • Create and run shell scripts (.sh files)
  • Write functions that accept parameters
  • Use loops to repeat tasks automatically
  • Automate batch processing of 3D models
  • Debug scripts when something goes wrong
  • Create professional workflows combining multiple tools

Shell Script Basics

What’s a Shell Script?

A shell script (.sh) contains multiple bash commands that run in sequence. Instead of typing commands one by one, you put them in a file and run them all at once.

Why use shell scripts?

  • Repeatability: Run the same task 100 times identically
  • Documentation: Commands are written down for reference
  • Complexity: Combine many commands logically
  • Automation: Schedule scripts to run automatically

Creating Your First Shell Script

Step 1: Open a text editor

notepad.exe my-first-script.sh

Step 2: Type this script

#!/bin/bash
# This is a comment - screen readers will read it
echo "Script is running!"
pwd
ls -1
echo "Script is done!"

Step 3: Save the file

  • In Notepad: Ctrl+S
  • Make sure filename ends in .sh
  • Save in an easy-to-find location (like Documents)

Note

Before you can run a .sh script, you must make it executable with chmod +x scriptname.sh. This is a one-time step per script. Without it, running ./script.sh will produce a “Permission denied” error even though the file exists.

Step 4: Make it executable and run the script

chmod +x my-first-script.sh
./my-first-script.sh

What happens: Bash runs each command in sequence and shows output.

Important

Always start shell scripts with #!/bin/bash (the “shebang” line). Without it, the system may use a different shell to run your script, which can cause unexpected errors — especially on systems where /bin/sh is not bash.

Important: The Shebang Line

The #!/bin/bash at the top of your script (called a “shebang”) tells the system which shell to use to run the script.

#!/bin/bash
# Now bash runs every command below
echo "Hello!"

Variables and Parameters

Using Variables

Variables store values you want to use later.

Example script:

#!/bin/bash
mypath="$HOME/Documents"
cd "$mypath"
echo "I am now in:"
pwd
ls -1

Breaking it down:

  • mypath="..." assigns the variable (no spaces around =)

Tip

Always quote variables that contain file paths: use "$mypath" not $mypath. Without quotes, spaces in folder names will break your script. This is one of the most common bash scripting mistakes.

  • "$mypath" uses the variable (quote it to handle spaces in paths)
  • Variables in bash are always referenced with $

Functions with Parameters

A function is reusable code that you can run with different inputs.

Example: A function that lists files in a folder

#!/bin/bash
list_folder() {
    local path="$1"
    echo "Contents of: $path"
    cd "$path"
    ls -1
}

# Use the function:
list_folder "$HOME/Documents"
list_folder "$HOME/Downloads"

What’s happening:

  • list_folder() defines the function
  • local path="$1" assigns the first argument to a local variable
  • $1 is the first argument passed to the function
  • Call the function with list_folder "path/to/folder"

Screen reader tip: When you call a function, bash will announce the results just like any command.


Loops - Repeating Tasks

Loop Over Files

Imagine you have 10 SCAD files and want to print their contents. You could do it 10 times manually, or use a loop.

Example: Print every .scad file in a folder

#!/bin/bash
for file in *.scad; do
    echo "=== File: $file ==="
    cat "$file"
    echo ""
done

What’s happening:

  • for file in *.scad; do iterates over each .scad file
  • $file holds the current filename
  • done ends the loop
  • Inside the loop, do something with each $file

Loop with a Counter

Example: Do something 5 times

#!/bin/bash
for i in $(seq 1 5); do
    echo "This is iteration number $i"
    # Do something here
done

What’s happening:

  • for i in $(seq 1 5) loops with i from 1 to 5
  • $i is the counter variable

Real-World Example - Batch Processing SCAD Files

Scenario

You have 10 OpenSCAD (.scad) files in a folder. You want to:

  1. List them all
  2. Check how many there are
  3. For each one, verify it exists

The Script

#!/bin/bash
scad_folder="$HOME/Documents/3D_Projects"
count=0

echo "Processing SCAD files in: $scad_folder"
echo ""

for file in "$scad_folder"/*.scad; do
    if [ -f "$file" ]; then
        echo "  Found: $(basename "$file")"
        count=$((count + 1))
    else
        echo "  Missing: $(basename "$file")"
    fi
done

echo ""
echo "Total files found: $count"
echo "Batch processing complete!"

Breaking it down:

  • scad_folder="..." = where to look
  • for file in "$scad_folder"/*.scad = find all .scad files
  • if [ -f "$file" ] = check if file exists and is a regular file
  • basename "$file" = just the filename (not the full path)
  • count=$((count + 1)) = increment the counter

Running the Script

  1. Save as batch-process.sh
  2. Edit scad_folder to match your real folder
  3. Make it executable and run it:
    chmod +x batch-process.sh
    ./batch-process.sh
    

Screen reader output:

Processing SCAD files in: /c/Users/YourName/Documents/3D_Projects

  Found: model1.scad
  Found: model2.scad
  Found: model3.scad
[... more files ...]

Total files found: 10
Batch processing complete!

Error Handling

Try-Style Checks with Exit Codes

What if something goes wrong? Use exit code checks:

Example:

#!/bin/bash
file="$HOME/nonexistent/path/file.txt"

if cat "$file" 2>/dev/null; then
    echo "File read successfully"
else
    echo "Error: Could not read file"
    echo "File path was: $file"
fi

What’s happening:

  • 2>/dev/null suppresses error messages from cat
  • if cat ...; then checks whether the command succeeded
  • else handles the failure gracefully

Screen reader advantage: Errors are announced clearly instead of crashing silently.

Validating Input

Example: Make sure a folder exists before processing

#!/bin/bash
process_folder() {
    local folder_path="$1"

    if [ ! -d "$folder_path" ]; then
        echo "Error: Folder does not exist: $folder_path"
        return 1
    fi

    echo "Processing folder: $folder_path"
    ls -1 "$folder_path"
}

process_folder "$HOME/Documents"

What’s happening:

  • [ ! -d "$folder_path" ] checks if the path is NOT a directory
  • return 1 exits the function early with a non-zero (error) status

Debugging Shell Scripts

Common Errors and Solutions

Error 1: “Command not found”

Cause: Typo in command name

Fix: Check spelling

# Wrong:
ech "hello"

# Correct:
echo "hello"

Error 2: “Variable is empty”

Cause: Variable was never assigned or has a typo

Fix: Make sure variable is set before using it

myvar="hello"  # Set first
echo "$myvar"  # Then use

Error 3: “No such file or directory”

Cause: Wrong folder path

Fix: Verify path exists

# Check if path exists:
if [ -d "$HOME/Documents" ]; then
    echo "Path exists"
fi

Error 4: “Permission denied”

Cause: Script not executable, or no write permission

Fix: Make the script executable, or check file permissions

chmod +x my-script.sh

Debugging Technique: Trace Output with set -x

Add set -x at the top of your script to print each command before it runs:

#!/bin/bash
set -x  # Enable trace mode
path_var="$HOME/Documents"
echo "Starting script. Path is: $path_var"

for file in "$path_var"/*; do
    echo "Processing: $file"
    # Do something with $file
    echo "Done with: $file"
done

echo "Script complete"

Your screen reader will announce each step, so you know where errors happen.


Creating Professional Workflows

Example 1: Automated Project Setup

Scenario: You start a new 3D printing project regularly. Instead of creating folders manually:

#!/bin/bash
read -p "Enter project name: " project_name
base_folder="$HOME/Documents/3D_Projects"
project_folder="$base_folder/$project_name"

# Create folder structure
mkdir -p "$project_folder"
mkdir -p "$project_folder/designs"
mkdir -p "$project_folder/output"
mkdir -p "$project_folder/notes"

# Create a README
cat > "$project_folder/README.txt" << EOF
# $project_name

Created: $(date)

## Designs
All .scad files go here.

## Output
STL and other exports go here.

## Notes
Project notes and observations.
EOF

echo "Project setup complete: $project_folder"

What it does:

  • Prompts for a project name
  • Creates folder structure for a new project
  • Sets up subfolders for designs, output, notes
  • Creates a README file automatically

Example 2: Batch File Verification

Scenario: Before processing, verify all required files exist:

#!/bin/bash
verify_project() {
    local project_folder="$1"
    local required_items=("README.txt" "designs" "output" "notes")
    local all_good=true

    for item in "${required_items[@]}"; do
        local path="$project_folder/$item"
        if [ -e "$path" ]; then
            echo "  Found: $item"
        else
            echo "  Missing: $item"
            all_good=false
        fi
    done

    if $all_good; then
        echo "All checks passed!"
        return 0
    else
        echo "Some files are missing!"
        return 1
    fi
}

# Use it:
project="$HOME/Documents/3D_Projects/MyKeychain"
if verify_project "$project"; then
    echo "Safe to proceed with processing"
fi

Screen Reader Tips for Shell Scripts

Making Script Output Readable

Problem: Script runs but output scrolls too fast or is hard to follow

Solution 1: Save to file

./my-script.sh > output.txt
notepad.exe output.txt

Solution 2: Use echo with clear sections

echo "========== STARTING =========="
echo ""
# ... script ...
echo ""
echo "========== COMPLETE =========="

Solution 3: Pause between major sections

echo "Pausing... Press Enter to continue"
read

Your screen reader will announce the pause, give you time to read output.

Announcing Progress

For long-running scripts:

#!/bin/bash
count=0
total=$(ls *.scad | wc -l)

for file in *.scad; do
    count=$((count + 1))
    echo "Processing $count of $total: $file"
    # Do something with $file
done

echo "All $count files processed!"

Practice Exercises

Exercise 1: Your First Shell Script

Goal: Create and run a simple shell script

Steps:

  1. Create file: notepad.exe hello.sh
  2. Type:
    #!/bin/bash
    echo "Hello from my first Git Bash shell script!"
    pwd
    ls -1
    
  3. Save, make executable, and run:
    chmod +x hello.sh
    ./hello.sh
    

Checkpoint: You should see output for each command.

Exercise 2: Script with a Variable

Goal: Use a variable to make the script flexible

Steps:

  1. Create file: notepad.exe smart-listing.sh
  2. Type:
    #!/bin/bash
    target_folder="$HOME/Documents"
    echo "Listing contents of: $target_folder"
    ls -1 "$target_folder"
    
  3. Edit target_folder to a real folder on your computer
  4. Run:
    chmod +x smart-listing.sh
    ./smart-listing.sh
    

Checkpoint: You should see listing of that specific folder.

Exercise 3: Function

Goal: Create a reusable function

Steps:

  1. Create file: notepad.exe navigate.sh
  2. Type:
    #!/bin/bash
    go_to() {
        local path="$1"
        if [ -d "$path" ]; then
            cd "$path"
            echo "Now in: $(pwd)"
            echo "Contents:"
            ls -1
        else
            echo "Path does not exist: $path"
        fi
    }
    
    # Test the function:
    go_to "$HOME/Documents"
    go_to "$HOME/Downloads"
    
  3. Run:
    chmod +x navigate.sh
    ./navigate.sh
    

Checkpoint: Both function calls should work, showing contents of each folder.

Exercise 4: Loop

Goal: Use a loop to repeat an action

Steps:

  1. Create file: notepad.exe repeat.sh
  2. Type:
    #!/bin/bash
    echo "Demonstrating a loop:"
    
    for i in $(seq 1 5); do
        echo "Iteration $i: Hello!"
    done
    
    echo "Loop complete!"
    
  3. Run:
    chmod +x repeat.sh
    ./repeat.sh
    

Checkpoint: Should print “Iteration 1” through “Iteration 5”.

Exercise 5: Real-World Script

Goal: Create a useful script for a real task

Steps:

  1. Create a folder: mkdir ~/Documents/TestFiles
  2. Create some test files:
    echo "test" > ~/Documents/TestFiles/file1.txt
    echo "test" > ~/Documents/TestFiles/file2.txt
    echo "test" > ~/Documents/TestFiles/file3.txt
    
  3. Create script: notepad.exe report.sh
  4. Type:
    #!/bin/bash
    folder="$HOME/Documents/TestFiles"
    count=0
    
    echo "=== FILE REPORT ==="
    echo "Folder: $folder"
    echo ""
    echo "Files:"
    for file in "$folder"/*; do
        echo "  - $(basename "$file")"
        count=$((count + 1))
    done
    echo ""
    echo "Total: $count files"
    echo "=== END REPORT ==="
    
  5. Run:
    chmod +x report.sh
    ./report.sh
    

Checkpoint: Should show report of all files in the test folder.


Quiz - Lesson GitBash.6

  1. What is a shell script?
  2. What file extension do bash shell scripts use?
  3. What is a variable in bash and how do you create one?
  4. What is a function and why would you use one?
  5. How do you run a shell script?
  6. What is a for loop and what does for file in *.scad; do do?
  7. What does [ -f "$file" ] check?
  8. How do you handle errors in a bash script?
  9. When would you use if [ ! -d "$path" ]; then?
  10. What technique makes shell script output readable for screen readers?

Extension Problems

  1. Auto-Backup Script: Create a bash script that copies all files from one folder to another, announcing progress
  2. File Counter: Write a function that counts files by extension (.txt, .scad, .stl, etc.)
  3. Folder Cleaner: Script that deletes files older than 30 days (with user confirmation)
  4. Project Template: Function that creates a complete project folder structure with all needed files
  5. Batch Rename: Script that renames all files in a folder according to a pattern
  6. Log Generator: Create a script that records what it does to a log file for later review
  7. Scheduled Task: Set up a script to run automatically using cron or Task Scheduler
  8. File Verifier: Check that all SCAD files in a folder have corresponding STL exports
  9. Report Generator: Create a summary report of all projects in a folder
  10. Error Tracker: Script that lists all commands that had errors and logs them with timestamps

Important Notes

  • Always test scripts on small sets of files first before running them on important data
  • Save your work regularly — use version naming if possible
  • Test error handling — make sure errors don’t crash silently
  • Document your scripts — use # comments so you remember what each part does
  • Backup before batch operations — if something goes wrong, you have the original

References


Unit Exam — Comprehensive Assessment


Estimated time: 60-90 minutes

Key Learning Outcomes Assessed

By completing this unit test, you will demonstrate:

  1. Understanding of file system navigation and path concepts
  2. Proficiency with file and folder manipulation commands
  3. Ability to redirect and pipe command output
  4. Knowledge of environment variables and aliases
  5. Screen-reader accessibility best practices in terminal environments
  6. Problem-solving and command chaining skills

Target Audience

Users who have completed Bash Lesson 0 through Bash Lesson 6 and need to demonstrate mastery of Git Bash fundamentals.

Instructions

Complete all sections below. For multiple choice, select the best answer. For short answers, write one to two sentences. For hands-on tasks, capture evidence (screenshots or output files) and submit alongside your answers.


Part A: Multiple Choice Questions (20 questions)

Select the best answer for each question. Each question is worth 1 point.

  1. What is the primary purpose of the PATH environment variable?

    • A) Store your home directory location
    • B) Tell the shell where to find executable programs
    • C) Configure the visual appearance of the terminal
    • D) Store the current working directory name
  2. Which command prints your current working directory in Git Bash?

    • A) ls -1
    • B) cd
    • C) pwd
    • D) whoami
  3. What does the ~ symbol represent in Git Bash paths?

    • A) The root directory
    • B) The current directory
    • C) The parent directory
    • D) The home directory
  4. How do you list only file names (not full details) in a way that is screen-reader friendly?

    • A) ls
    • B) ls -1
    • C) ls -l
    • D) cat -1
  5. Which command creates a new empty file in Git Bash?

    • A) mkdir filename
    • B) touch filename
    • C) new filename
    • D) echo filename
  6. What is the difference between > and >>?

    • A) > redirects to file, >> displays on screen
    • B) > overwrites a file, >> appends to a file
    • C) They do the same thing
    • D) > is for text, >> is for binary
  7. What does the pipe operator | do?

    • A) Creates a folder
    • B) Sends the output of one command to the input of another
    • C) Deletes files matching a pattern
    • D) Lists all processes
  8. Which command copies a file in Git Bash?

    • A) mv
    • B) rm
    • C) cp
    • D) cd
  9. How do you rename a file from oldname.txt to newname.txt in Git Bash?

    • A) cp oldname.txt newname.txt
    • B) mv oldname.txt newname.txt
    • C) rename oldname.txt newname.txt
    • D) rn oldname.txt newname.txt
  10. What is the purpose of grep in Git Bash piping?

    • A) Find files in a directory
    • B) Search for text patterns within output or files
    • C) Select a string to copy to clipboard
    • D) Select which shell to use
  11. Which key allows you to autocomplete a path in Git Bash?

    • A) Ctrl + A
    • B) Ctrl + E
    • C) Tab
    • D) Space
  12. How do you copy text to the Windows clipboard from Git Bash?

    • A) cat filename > clipboard
    • B) cat filename | clip
    • C) copy filename
    • D) cat filename | paste

Tip

Use which programname to check whether a program is in your PATH and find its full path. If which openscad returns nothing, OpenSCAD is not in your PATH and you’ll need to add it or call it by its full path.

  1. What does which openscad do?

    • A) Opens the OpenSCAD application
    • B) Gets help about the openscad command
    • C) Locates the full path of the openscad executable
    • D) Lists all available commands
  2. Which wildcard matches any single character in Git Bash?

    • A) *
    • B) ?
    • C) %
    • D) #
  3. What is the purpose of ./ before a script name?

    • A) Run a script in the current directory
    • B) Execute all commands in parallel
    • C) Combine multiple commands
    • D) Create an alias
  4. How do you create a temporary alias in Git Bash?

    • A) set-alias preview='openscad'
    • B) alias preview='openscad'
    • C) new-alias preview openscad
    • D) preview = openscad

Important

Aliases saved only in the terminal session are lost when you close Git Bash. To make an alias permanent, add it to ~/.bashrc. After editing .bashrc, run source ~/.bashrc to apply changes without restarting.

  1. Where is a Git Bash alias typically stored to persist across sessions?
    • A) C:\Program Files\Git\profile.sh
    • B) In the ~/.bashrc file
    • C) ~/bash_profile
    • D) Aliases cannot be made permanent

Important

Ctrl+C is the universal “abort” key — it stops any running command immediately and returns you to the prompt. This works in Git Bash, CMD, and PowerShell. Use it whenever a command hangs, loops unexpectedly, or produces unwanted output.

  1. How do you abort a long-running command in Git Bash?

    • A) Press Escape
    • B) Press Ctrl + X
    • C) Press Ctrl + C
    • D) Press Alt + F4
  2. What command shows the history of previously run commands in Git Bash?

    • A) history
    • B) get-history
    • C) show-history
    • D) bash-history

Tip

After editing ~/.bashrc, run source ~/.bashrc to apply your changes immediately without restarting Git Bash. Without this step, new aliases and variables won’t take effect until the next time you open a terminal.

  1. How do you reload your .bashrc without restarting Git Bash?
    • A) Use reload ~/.bashrc in the terminal
    • B) Use source ~/.bashrc
    • C) Use the Windows Control Panel
    • D) .bashrc reloads automatically

Part B: Short Answer Questions (10 questions)

Answer each question in one to two sentences. Each question is worth 2 points.

  1. Explain the difference between absolute and relative paths. Give one example of each.

  2. Why is ls -1 preferred over ls for screen reader users? Describe what flag combination you would use to list only directories.

  3. What is the purpose of redirecting output to a file, and give an example of when you would use > instead of >>?

  4. Describe what would happen if you ran rm -r ~/Documents/my_folder and why this command should be used carefully.

  5. How would you search for all files with a .scad extension in your current directory? Write the command.

  6. Explain what happens when you pipe the output of ls -1 into clip. What would you do next?

  7. What is an environment variable, and give one example of how you might use it in Git Bash.

  8. If a program is not in your PATH, what two methods could you use to run it from Git Bash?

  9. Describe how you would open a file in Notepad and also add a line to it from Git Bash.

  10. What is one strategy you would use if your screen reader stops announcing terminal output while using Git Bash?


Part C: Hands-On Tasks (10 tasks)

Complete each task and capture evidence (screenshots, output files, or command transcripts). Each task is worth 3 points.

Tasks 1-5: File System and Navigation

  1. Create a folder structure ~/Documents/GitBash_Assessment/Projects using a single command. Capture the ls -1 output showing the creation.

  2. Create five files named project_1.scad, project_2.scad, project_3.txt, notes_1.txt, and notes_2.txt inside the Projects folder. Use wildcards to list only .scad files, then capture the output.

  3. Copy the entire Projects folder to Projects_Backup using cp -r. Capture the ls -1 output showing both folders exist.

  4. Move (rename) project_1.scad to project_1_final.scad. Capture the ls -1 output showing the renamed file.

  5. Delete notes_1.txt and notes_2.txt using a single rm command with wildcards. Capture the final ls -1 output.

Tasks 6-10: Advanced Operations and Scripting

  1. Create a file called my_data.txt with at least four lines using echo and >>. Then read it with cat my_data.txt and capture the output.

  2. Use grep to search for a keyword (e.g., “project”) in my_data.txt and pipe the results to clip. Paste the results into Notepad and capture a screenshot.

  3. List all files in the Projects folder and redirect the output to projects_list.txt. Open it in Notepad and capture a screenshot of the file.

  4. Create a temporary alias called myls that runs ls -1, test it, and capture the output. Then explain what would be required to make it persistent.

  5. Run man ls (or ls --help) and redirect the output to help_output.txt. Open the file in Notepad and capture a screenshot showing at least the first page of help content.


Grading Rubric

SectionQuestionsPoints EachTotal
Multiple Choice20120
Short Answer10220
Hands-On Tasks10330
Total40-70

Passing Score: 49 points (70%)


Helpful Resources for Review


Submission Checklist

  • All 20 multiple choice questions answered
  • All 10 short answer questions answered (1-2 sentences each)
  • All 10 hands-on tasks completed with evidence captured
  • Files/screenshots organized and labeled clearly
  • Submission includes this checklist

3dMake-Accessible Design with OpenSCAD

This section covers the complete 3D design and printing workflow using OpenSCAD, 3DMake, and accessible tools. Students progress from basic primitives through advanced parametric design and stakeholder-centric projects.

Time commitment: 30-40 hours instruction + projects

Skills gained: 3D modeling, parametric design, automated workflows, tolerance testing, quality assurance

3dMake Foundation & Design — Complete Course Compendium

Course: Accessible 3D Printing with OpenSCAD and 3DMake Track: 3dMake Certification — High School Distance Learning Contents: Instructional Framework · Curriculum Guide · All 11 Lessons · Final Exam · Quick Reference Guide


Part I — Instructional Framework

A pedagogical overview of the 3DMake and OpenSCAD ecosystem for secondary STEM education.

The Architecture of Programmatic Design

Programmatic CAD differs from standard industry tools like Fusion 360 or SolidWorks by utilizing a “code-as-model” philosophy. OpenSCAD, the primary engine supported by 3DMake, uses a functional programming language to define three-dimensional volumes.1 This approach is particularly robust for parametric design, where the dimensions of an object are defined as variables, allowing for instantaneous reconfiguration without manual rebuilding.2 3DMake enhances this by providing a unified command-line interface (CLI) to manage the entire process, from editing source files to triggering remote print jobs through interfaces like OctoPrint or Bambu Connect.3

The educational value of this toolchain lies in its transparency. Students are not hidden behind a proprietary user interface; they interact directly with the file system, configuration files, and API integrations. This exposure fosters a deeper understanding of how modern software interacts with hardware — a skill set increasingly vital in robotics and aerospace engineering.4 However, the shift to a terminal-based environment requires a structured instructional approach to overcome initial barriers to entry.

AI Integration and Model Descriptive Feedback

The integration of artificial intelligence into the 3DMake workflow represents a significant advancement in democratizing CAD for students with varying levels of spatial reasoning skills. The 3dm info command acts as a multimodal bridge between the deterministic world of OpenSCAD and the probabilistic world of LLMs.3

When a student executes 3dm info, the system initiates a rendering pipeline, generating multiple viewpoints of the current model, which are packaged as image data and sent to the configured AI (e.g., Gemini) along with a descriptive prompt. The AI’s response provides a summary that can include the model’s intended function, aesthetic qualities, and potential engineering failures.3

The Limits of AI Spatial Reasoning

While powerful, current LLMs do not possess a true “3D world model” — they are trained primarily on 2D images and text.5 Common failures include:

  • Detached Geometry: The AI might describe a “table” even if the legs are hovering below the tabletop.5
  • Scale Misinterpretation: Without a reference object in the render, the AI may misjudge scale, leading to inappropriate feedback on wall thickness.3

Caution

Hallucination of Detail: The AI may describe features it expects to see (like “engraved text”) even if the student’s code failed to render them.5

Important

AI is a verification assistant, not a source of truth. The deterministic rendering of OpenSCAD remains the final authority on geometry. AI is most useful as a “sanity check” to catch obvious mistakes before wasting filament.3

Occupational Health and Safety

Safety in the 3DMake workflow extends to the physical act of printing, which involves thermal, chemical, and mechanical risks. The National Institute for Occupational Safety and Health (NIOSH) provides a clear framework for these risks.6

Chemical and Particulate Emissions

The melting of plastic filament is a thermal degradation process. ABS releases styrene, a known respiratory irritant and potential carcinogen.6 Even PLA emits millions of ultrafine particles (UFPs) per minute during extrusion — particles smaller than 100 nanometers that can penetrate deep into the lungs.6

Emission ComponentPrimary Source FilamentsMitigation Strategy

Warning

ABS and ASA filaments release styrene — a respiratory irritant and potential carcinogen. Always use an enclosed printer with carbon filtration for these materials.

| Styrene | ABS, ASA | Enclosed printer with carbon filtration.6 | | Formaldehyde | POM, Nylon | High-efficiency external ventilation.6 | | Ultrafine Particles | All filaments | HEPA filtration and “20-minute” settling period.7 | | Volatile Organic Compounds | All filaments | Minimum 6 air changes per hour in the room.8 |

Physical and Mechanical Hazards

The extruder nozzle can reach 260°C and the heated build plate can reach 110°C.9 Standard operating procedures for a student lab must include:

  • Pre-use Inspection: Check for frayed wires, loose belts, and a clear build surface.8
  • Environmental Controls: Prohibit eating or drinking in the print area to avoid ingestion of contaminants.9
  • Emergency Response: Locate the nearest ABC fire extinguisher (Class D for metal prints).10
  • Post-Print Cooling: Ensure the printer has cooled below 30°C before removing the model.8

Challenges Inherent in the OpenSCAD Language

OpenSCAD’s declarative nature and unique rendering kernel present specific hurdles for students. Unlike imperative languages, OpenSCAD describes what a shape is, not how to build it step by step.11

Immutable State

Note

Variables in OpenSCAD are more like constants within a scope. If a student writes x = 5; x = 10;, OpenSCAD will use the last assigned value (x = 10) for the entire script.12 This requires adopting a functional programming mindset where geometry is defined by its state rather than a sequence of movements.

Performance Bottlenecks

Note

OpenSCAD’s CGAL geometry kernel is highly accurate but slow for certain operations. Minkowski sums (used for rounding corners) can take minutes at high $fn values. Keep $fn low while developing and only raise it for final renders.13 OpenSCAD also has no native “fillet” command — students must construct these manually using boolean subtractions or libraries like BOSL2.2

The Absolute Coordinate Barrier

OpenSCAD has no concept of relative constraints — every object is positioned in absolute (X, Y, Z) space.14 If a student moves one part, they must manually calculate and update the translation of every related part. This necessitates heavy use of variables and mathematical offsets.14

Technical Limitations of 3DMake

LimitationTechnical Root CauseEducational Impact
CLI BarrierNo graphical interface for configurationSteep learning curve for students with zero terminal experience.3

Caution

AI features (3dm info descriptions, 3dm orient) require an active internet connection and a configured API key. These features will fail silently on offline school networks — plan accordingly.

| API Dependency | AI features require external internet and API keys | Advanced features fail in offline school networks.3 | | Slicer Lock-in | Reliant on external templates for G-code generation | Students may not learn the nuance of slicing settings.3 | | Feedback Latency | No real-time “live” preview in the editor | The edit-compile-view cycle is slower than GUI-based CAD.3 |

Caution

Non-manifold geometry (zero-thickness walls or improperly closed polyhedrons) will generate an STL without warning from 3dm build, but the slice command may then fail or produce corrupt G-code. Always verify mesh integrity before printing.15 Students must learn mesh verification skills using tools like MeshLab or PrusaSlicer’s repair functions.16

Local Resources — Utah Makerspaces

Utah provides a broad network of makerspaces across public libraries, universities, and community nonprofits.

Public Library Makerspaces

Salt Lake City Public Library – Creative Lab (Main + Marmalade, Glendale, Sprague branches): 3D printers, Cricut cutters, Adobe Creative Cloud, sound booth, and more.17

Salt Lake County Library – Create Spaces (Daybreak, Granite, Holladay, Kearns, Magna, Sandy): Flashforge and LulzBot 3D printers, VR/robotics kits, audio/visual studios.18

Weber County Library Makerspaces: Laser cutters, vinyl cutters, embroidery machines, and design software stations.19

Washington County Library – Sid Atkin Makerspace (St. George): Large-format 3D printers, CNC cutters, sewing machines, electronics kits, and woodworking tools.20

Logan Library – Cytiva STEM Makerspace (Cache County): Bambu 3D printers, laser engravers, heat presses, and digitization tools.21

University & Higher-Education Makerspaces

University of Utah – Marriott Library ProtoSpace: Prusa MK4 and Prusa XL printers, 3D scanners, open to students and staff.22

Utah Tech University – Jr. Makerspace (St. George): Supports K–12 and community visitors with training and STEM events.23

Southern Utah University – Thunderworks Makerspace (Cedar City): CNC tools, 3D printers, electronics benches, and generous public hours.23

Regional STEM Hubs

Make Salt Lake: Nonprofit makerspace with woodshop, metal shop, laser cutters, 3D printer labs, and electronics benches.23

The Utah STEM Action Center’s Innovation Hub Network maintains a statewide directory across all counties: stem.utah.gov/innovationhubnetwork.

National Makerspace Directories

Supplemental Learning Resources

References

Deck, T. (2025). 3DMake: A command-line tool for 3D printing workflows. GitHub. https://github.com/tdeck/3dmake Gohde, J., & Kintel, M. (2021). Programming with OpenSCAD: A beginner’s guide to coding 3D-printable objects. No Starch Press. Gonzalez Avila, J. F., Pietrzak, T., & Casiez, G. (2024). Understanding the challenges of OpenSCAD users for 3D printing. ACM UIST. NIOSH. (2024). Approaches to safe 3D printing. https://www.cdc.gov/niosh/blogs/2024/safe-3d-printing.html Ohio State University EHS. (2026). 3D printer safety concerns and ventilation. https://ehs.osu.edu/kb/3d-printer-safety Washington State Department of Health. (2026). 3D printer and filament selection for safe school environments. https://doh.wa.gov/community-and-environment/schools/3d-printers

  • https://www.nationofmakers.us/find-a-maker-organization
  • https://makerspace.com/directory/
  • https://makerspacedir.com/
  • https://workmakecreate.com/

Part II — Curriculum Guide

Structure, learning paths, and reference material for the complete 11-lesson course.

Overview

This 11-lesson curriculum (plus 4 reference appendices) teaches non-visual 3D modeling, parametric design principles, and the complete 3D printing workflow through integrated projects. Each lesson builds on prior knowledge, introducing real-world examples and hands-on activities.

Target Audience: High school and early undergraduate students, makers, and anyone interested in programmatic CAD and 3D printing Estimated Total Time: 30–40 hours (11 lessons + 4 appendices + projects)

Lesson Structure at a Glance

#TitleDurationLevelKey Project
1Environmental Configuration2.5–3.5 hrsBeginnerProject scaffold
2Geometric Primitives & CSG60 minBeginner3 CSG examples
3Parametric Architecture2.5 hrsBeginner+Parametric bracket
4AI Verification2–2.5 hrsIntermediateAI-notes.md
5Safety & Physical Interface2.5–3.5 hrsIntermediatePre-print checklist
63dm Commands & Text Embossing2.5–3.5 hrsIntermediateKeycap variants
7Parametric Transforms3–3.5 hrsIntermediate+Phone Stand
8Advanced Parametric Design90–120 minAdvancedStackable Bins
9Automation & Workflows2.5–3.5 hrsAdvancedBatch build script
10Troubleshooting & Mastery5–6 hrsAdvanced3 complete projects
11Stakeholder-Centric Design3.5–4.5 hrsAdvanced+Jewelry Holder

Learning Paths

Path 1 — Complete Mastery (30–40 hours): Lessons 1–11 + all appendices. Best for first-time learners wanting comprehensive understanding.

Path 2 — Design Focus (Fast Track): Lessons 1 → 2 → 3 → 6 → 7 → 8 → 9. Best for experienced designers new to programmatic CAD.

Path 3 — Project-Based: Lessons 1–3 → 6 (Keycap) → 7 (Phone Stand) → 8 (Bins) → 9 (Automation) → 10 (Troubleshooting) → 11 (Leadership). Best for learning by doing.

Path 4 — Safety & Printing Focus: Lessons 1, 2, 5, 6, 10 + Appendices A, B, C. Best for practical printing and quality focus.

Detailed Lesson Descriptions

Lesson 1: Environmental Configuration and the Developer Workflow

Install and configure 3dMake, create a project scaffold, and run your first build. Covers installation and tool verification, project structure (src/, build/, 3dmake.toml), parametric design philosophy, and the 3dm build command. Checkpoint: You can initialize a project, edit a parametric model, and generate an STL file.

Lesson 2: Geometric Primitives and Constructive Solid Geometry

Combine basic shapes using boolean operations. Covers cube(), sphere(), cylinder(); CSG operations (union(), difference(), intersection()); the 0.001 offset rule for non-manifold geometry; and low-resolution renders for faster debugging. Checkpoint: You understand CSG operations and can diagnose common geometry issues.

Lesson 3: Parametric Architecture and Modular Libraries

Create reusable modules and organize code into libraries using the DRY principle. Covers module definitions, derived calculations, library organization (lib/ folder), BOSL2, and low-resolution testing with $fn. Checkpoint: You can create parametric modules and organize code into libraries.

Lesson 4: AI-Enhanced Verification and Multimodal Feedback

Use 3dm info to generate AI diagnostics and validate designs. Covers the 3dm info command, AI-generated descriptions, AI limitations, privacy and governance, and prompt engineering basics. Checkpoint: You can use AI tools to supplement your design validation.

Lesson 5: Safety Protocols and the Physical Fabrication Interface

Transition from digital design to physical printing. Covers the Hierarchy of Controls, chemical and particulate emissions, pre-print environmental and equipment checks, post-print inspection, and spool metadata. Checkpoint: You understand safety procedures and can safely conduct supervised prints.

Lesson 6: Practical 3dm Commands and Text Embossing

Master key 3dm commands by building a customizable keycap. Covers 3dm info, 3dm preview, 3dm orient, 3dm slice, and text embossing with linear_extrude() and text(). Project: Generate 3+ keycap variants (small, medium, large). Checkpoint: You can generate keycaps with embossed text and understand all major 3dm commands.

Lesson 7: Parametric Transforms and the Phone Stand Project

Apply transforms to build a multi-part assembly. Covers translate(), rotate(), scale(), Minkowski sum for edge rounding, multi-part assemblies, and parametric angle variations. Project: Phone stand with configurations for phones, tablets, and documents. Checkpoint: You can design multi-part assemblies with positioned components.

Lesson 8: Advanced Parametric Design and Interlocking Features

Design tolerance-critical assemblies where parts snap together. Covers tolerance and clearance management, stack-up error, interlocking rims, snap-fit connectors, and chamfers. Project: Stackable storage bins — test different stack_clear values, create size variants, add optional dividers. Checkpoint: You understand tolerance management and can design stackable assemblies.

Lesson 9: Automation and 3dm Workflows

Automate design workflows using shell scripts. Covers chaining 3dm commands with &&, shell script batch processing, library management (3dm lib), variant testing matrices, and production build workflows. Checkpoint: You can automate design workflows and manage parametric variants at scale.

Lesson 10: Hands-On Practice Exercises and Troubleshooting

Capstone lesson synthesizing all prior learning across three exercise sets: Set A (guided projects: Phone Stand, Keycap Set, Storage System), Set B (problem diagnosis: non-manifold geometry, print failure prevention, dimensional accuracy), and Set C (validation and documentation templates). Checkpoint: You can complete real projects from concept to verified print.

Lesson 11: Stakeholder-Centric Design and the Beaded Jewelry Project

Design for real users, not just yourself. Covers stakeholder identification and interview techniques, extracting functional requirements, defining measurable acceptance criteria, design iteration based on feedback, and documentation for reproducibility. Project: Beaded jewelry bracelet holder — interview a stakeholder, extract requirements, design parametrically, test with actual bracelets, iterate. Checkpoint: You can conduct a real interview, translate needs into measurable requirements, and iterate a design based on user feedback.

Project Completion Tracking

ProjectLessonsOutput FilesEst. Print Time
Keycap Set1–65+ SCAD files, 3+ STL files15–30 min total
Phone Stand1–71 SCAD with 3+ variants30–60 min total
Storage Bins1–81 parametric SCAD, 3 sizes60–90 min total

Assessment and Completion

Each lesson includes learning objectives, step-by-step tasks, checkpoints, a 10-question self-assessment quiz, and 10 extension problems.

Lesson completion criteria: Watched/read entire lesson · Completed all step-by-step tasks · Reached all checkpoints · Answered quiz questions · Attempted at least 3 extension problems · Documented findings.

Project completion criteria: Code builds without errors · All parameters functional · STL generated and inspected · Measurements documented · Assembly tested (if multi-part) · README or documentation included.

Appendices Overview

AppendixFocusSizeUse When
A: Comprehensive Slicing GuidePrusaSlicer, Bambu Studio, Cura, OrcaSlicer, and more1,500+ linesSlicing questions, slicer reference
B: Material Properties & SelectionPLA, PETG, ABS, TPU, Polycarbonate, Nylon — properties, settings, decision tree1,200+ linesChoosing material, troubleshooting prints
C: Tolerance Testing & QA MatrixMeasurement procedures, functional testing, stack-up calculations1,200+ linesQuality verification, measurement techniques
D: PowerShell IntegrationBatch processing, automation scripts, workflow integration1,100+ linesBuilding automation, batch processing
E: Advanced OpenSCAD ConceptsGears, batch/statistical analysis, performance optimization, recursionOptionalSpecialized/advanced applications

Accessibility Features

This curriculum is designed for non-visual learners: text descriptions of all models via 3dm info, tactile 2D previews via 3dm preview, structured written documentation, command-line based (no graphical interface required), and measurement-based validation without visual inspection.

Next Steps After Completion

Upon completing this curriculum, students are ready for: advanced BOSL2 library features and parametric assemblies; multi-material printing (TPU, Nylon, etc.); mechanical assemblies with bearings, gears, and mechanisms; community contribution via shared designs and libraries; and professional applications in product design, prototyping, and manufacturing.

Curriculum Revision History

VersionDateChanges
2.1Feb 2026Added Appendix E (Advanced OpenSCAD); Enhanced Lessons 3, 6, 7, 8, 9 with advanced topics
2.0Feb 2026Added Lesson 11 (Stakeholder Design) + 4 Appendices; Consolidated Units 0–3 content
1.0Feb 2026Initial comprehensive curriculum with 10 lessons + 5 projects

Part III — All 11 Lessons

Lesson 1 — Environmental Configuration and the Developer Workflow

Estimated Time: 60–90 minutes
Course: 3dMake Certification — High School Distance Learning Track


A Message to You Before We Begin

Welcome to your first lesson. If you’ve never used a command line, never written code, or never sent a file to a 3D printer before, you are in exactly the right place. This lesson is designed so that someone who has done none of those things can follow every step.

If you have done some of those things, you’ll still find this lesson useful — because the way 3D printing tools fit together is different from most software you’ve used before, and understanding the full picture from the start will save you real trouble later.

By the time you finish this lesson, you will have your tools installed and working, you’ll understand the basic logic of the coordinate system your designs live in, and you’ll have run your first parametric 3D model through the complete build-and-verify workflow.

Take your time here. The concepts in this first lesson are the foundation everything else is built on.


Learning Objectives

By the end of this lesson you will be able to:

  • Install and verify the 3dMake toolchain on Windows, macOS, and Linux
  • Understand the OpenSCAD coordinate system and unit conventions
  • Write and build your first parametric .scad file
  • Read and interpret 3dm info output without a visual display
  • Use the core developer workflow: edit → build → verify

Concept 1: What Is Parametric 3D Design?

The Two Ways to Design for 3D Printing

There are two ways to design a 3D object for printing. The first way is to use a visual editor — a program where you click, drag, and push shapes around the screen until they look right. Programs like Tinkercad work this way. They’re intuitive and fast for simple objects, but they have a limitation: if you want to change the size of something, you often have to go back and manually adjust every related dimension by hand.

The second way is to use code. You write instructions that describe your object mathematically. “Make a box that is 30 millimeters wide, 20 millimeters deep, and 10 millimeters tall.” If you later decide that 30 mm is too narrow and 40 mm would be better, you change one number, and the model automatically updates everywhere that number is used. This is called parametric design — the word “parametric” means the design is controlled by parameters, which are the named values you can adjust.

Parametric design is how professional engineers create parts. An engineer designing a phone stand might create one file that works for phone models ranging from 60 to 90 mm wide just by changing a single variable. That single source file is the design concept, and specific values turn it into specific objects.

OpenSCAD is the tool you’ll use for parametric design in this course. Instead of clicking and dragging, you write code that describes shapes and their relationships. The learning curve is steeper than a visual editor at the very beginning, but within a few lessons you’ll be creating things that would be extremely difficult or impossible in a drag-and-drop tool.

What 3dMake Does

OpenSCAD by itself is powerful, but its workflow has a lot of friction. To go from code to a printable file, you’d normally need to open OpenSCAD, manually trigger a render, export an STL file, open a separate slicer program, check for geometry errors, and save the output. That’s a lot of steps just to see if your idea works.

3dMake is a tool that wraps around OpenSCAD and smooths out that friction. When you type 3dm build, it runs the entire compile-and-export process for you automatically. When you type 3dm info, it analyzes your model and tells you its dimensions, volume, and a description in plain language. The more time you spend designing rather than managing files, the faster you learn and the more you make.

Think of it this way: OpenSCAD is the engine, and 3dMake is the dashboard. You could use the engine directly, but the dashboard makes it dramatically easier to operate.


Concept 2: The Command Line

What It Is and Why We Use It

You’re going to be working with the command line throughout this course. If you’ve mostly used computers by clicking icons and menus, the command line can feel strange at first — but it’s really just a different way to talk to your computer.

Here is the basic idea: the command line is a text box where you type an instruction, press Enter, and the computer does something and prints a response. That’s the whole interaction model. Type a command. Press Enter. Read the result. Repeat.

For example, if you type 3dm build and press Enter, the computer finds the 3dMake program, tells it to build your project, and then prints either a success message with your model’s dimensions, or an error message with a line number pointing to the problem. This feedback loop is tight, fast, and precise — which is exactly what you want when you’re designing and testing.

The command line has another advantage: it’s repeatable. If you type a command that works, you can type it again. You can save it in a script and run it automatically. You can share it with someone else, and they can run the same command and get the same result. Clicking around menus is difficult to document and impossible to automate; text commands are both.

Which Terminal to Use

Windows users: You have two options. PowerShell is the modern choice and the one we recommend — it’s more powerful and consistent with what you’ll find in professional environments. To open it, press the Windows key, type PowerShell, and press Enter. Alternatively, Command Prompt (CMD) is an older option that still works for basic tasks. This course provides code examples for both.

macOS users: Open Terminal by going to Applications → Utilities → Terminal. It runs a shell called bash (or zsh on newer Macs — both work for this course).

Linux users: You almost certainly already know how to open a terminal. If not, look for “Terminal” in your applications menu.

A Few Things to Know Before We Start

  • On macOS and Linux, file paths use forward slashes: src/main.scad
  • On Windows, file paths use backslashes: src\main.scad
  • Commands are case-sensitive on macOS and Linux3DM and 3dm are different things, and only the lowercase version will work
  • When a command says it “isn’t found,” it almost never means the software isn’t installed — it usually means the terminal opened before the installation updated its search path (we’ll cover how to fix this in Step 1)

Step 1 — Install the 3dMake Toolchain

Understanding What You’re Installing

You’re installing two pieces of software that work together:

OpenSCAD is the underlying 3D geometry engine. It reads your .scad code files and turns them into 3D model files (specifically .stl files). You can think of it like a compiler for 3D geometry — the same way a Python interpreter turns Python code into running behavior, OpenSCAD turns design code into physical geometry. You don’t need to interact with OpenSCAD directly very often; 3dMake does it for you.

3dMake is the project management layer that sits on top of OpenSCAD. It organizes your project files, runs OpenSCAD with the right settings, analyzes your model output, and provides the plain-English 3dm info descriptions you’ll use to verify your work.

The installer sets up both. Run the appropriate command for your operating system below, let it finish completely, and then run the verification commands before doing anything else.

Installation Commands

Linux and macOS (bash terminal):

# Download and run the official installer
curl -fsSL https://get.3dmake.dev | bash

# After it finishes, verify both tools are installed correctly.
# Both of these commands should print version numbers, not errors.
3dm --version
openscad --version

Windows (PowerShell):

# Install using Windows Package Manager
winget install 3dMake.3dMake

# If winget isn't available, download the installer directly:
# https://3dmake.dev/install
# Run the downloaded installer, then open a NEW PowerShell window.

# Verify the installation:
3dm --version
openscad --version

Windows (Command Prompt / CMD):

REM After installation, open a NEW CMD window and verify:
3dm --version
openscad --version

REM If you see "not recognized as an internal or external command",
REM see the troubleshooting section below.

What the Version Numbers Mean

When you run 3dm --version, you should see output like 3dMake v1.4.2 (the exact number doesn’t matter as long as something prints). When you run openscad --version, you should see OpenSCAD version 2021.01 or later. If either command produces an error instead of a version number, something went wrong with the installation. Read the troubleshooting section before moving on.

Troubleshooting Installation

“command not found” or “is not recognized as an internal or external command”

This is the most common issue and it almost always has the same cause: your terminal session started before the installer ran. When the installer finishes, it adds the 3dMake folder to a system setting called the PATH — a list of folders your computer searches when you type a command name. But a terminal that was already open when the installer ran doesn’t know about the change. The fix is simple: close your terminal completely and open a new one, then try the verification commands again.

What is PATH? When you type 3dm at the command line, your computer doesn’t search your entire hard drive — that would take forever. Instead, it searches only the folders listed in PATH. If 3dMake’s folder isn’t in that list, the computer genuinely can’t find the program even though it’s installed. Closing and reopening the terminal forces it to reload the PATH list.

If opening a new terminal doesn’t fix it, you may need to add the folder manually. On Windows, search the Start menu for “Edit the system environment variables,” click “Environment Variables,” and add the 3dMake installation folder to the Path variable. On macOS/Linux, add the folder path to your ~/.bashrc or ~/.zshrc file and restart the terminal.

OpenSCAD version too old

3dMake requires OpenSCAD 2021 or later. If you have an older version from a previous installation, download the latest release from openscad.org, uninstall the old version, and install the new one.


Concept 3: The Coordinate System — Where Objects Live in 3D Space

Why You Need to Understand This Before Writing Code

Imagine you’re on the phone with a friend trying to tell them where to place a chair in an empty room. You’d need to agree on two things: where to measure from (a corner? the center of the room?), and which directions count as “forward,” “sideways,” and “up.” Without that shared reference, your instructions are meaningless.

OpenSCAD works exactly the same way. Every object you create lives at a specific location in 3D space. That space has a fixed starting point called the origin and three directions called axes. If you don’t know these, you’ll place objects and wonder why they appear where they do.

The Three Axes

OpenSCAD uses a right-handed XYZ coordinate system — a standard that’s shared by engineering software worldwide, so learning it here transfers directly to other professional tools.

Picture a 3D printer’s build plate in front of you:

  • X axis — points to the right across the build plate. Positive X is rightward; negative X is leftward.
  • Y axis — points away from you, toward the back of the build plate. Positive Y is away from you; negative Y is toward you.
  • Z axis — points straight up, perpendicular to the build plate. Positive Z is upward; negative Z would be underground.

The origin — the point (0, 0, 0) — sits at the front-left corner of the build space, right at bed level. When you type cube([20, 20, 10]) without any translation, it appears with its front-left-bottom corner at the origin, extending 20 mm to the right, 20 mm back, and 10 mm up.

Why This Matters for Printing

Because the Z axis points up and the origin is at bed level, any geometry with a negative Z coordinate would be “underground” — below the build plate. The printer can’t print there. Part of your job when designing is to make sure your entire model lives in positive Z space (Z ≥ 0) so it sits on the bed correctly.

Units: Always Millimeters

OpenSCAD has no built-in concept of units — it just works with numbers. The convention in this course (and in the 3D printing community generally) is that all dimensions are in millimeters. This is not optional or adjustable — it’s a universal agreement.

When you write cube([30, 20, 10]), that means 30 mm × 20 mm × 10 mm. If you accidentally think in centimeters and write cube([3, 2, 1]) meaning “3 cm by 2 cm by 1 cm,” OpenSCAD will treat those as millimeters and your print will come out ten times too small. Always, always, always think in millimeters.

The center Parameter: Where Does the Object Anchor?

Every 3D primitive in OpenSCAD has a center parameter. This is one of the most important things to understand early, because it affects where objects appear and how easy your placement math is.

center=false (this is the default — it applies if you don’t write anything): the object’s bottom-left-front corner sits at the position you specify. A cube([20, 20, 10]) with no translation occupies the space from X=0 to X=20, Y=0 to Y=20, Z=0 to Z=10. The object lives entirely in positive space and sits neatly on the build plate.

center=true: the object’s geometric center sits at the position you specify. The same cube at the origin would extend from X=−10 to X=10, Y=−10 to Y=10, Z=−5 to Z=5. Half of it would be underground — which means if you print it without moving it up first, you’ll only get the top half.

Neither option is wrong. You choose based on which makes your math simpler. For parts that should sit on the build plate, center=false is more natural. For parts you want to rotate around their center, center=true is much cleaner.

// Demonstrating center=false vs center=true
// Build this and use 3dm info to see the bounding box of each shape.

// This cube sits on the bed naturally — its bottom is at Z=0.
cube([20, 20, 10]);                    // corner at origin; occupies X:0–20, Y:0–20, Z:0–10

// This cube straddles the origin — half of it is underground!
// Move it sideways with translate() so it doesn't overlap the first one.
translate([35, 0, 0])
  cube([20, 20, 10], center=true);     // center at origin; occupies X:25–45, Y:-10–10, Z:-5–5

// A small red sphere marks where the origin is.
color("red") sphere(r=1.5, $fn=16);

// Colored cylinders mark the positive direction of each axis.
color("red")   translate([25, 0, 0]) cylinder(r=0.5, h=1, $fn=8);  // +X
color("green") translate([0, 25, 0]) cylinder(r=0.5, h=1, $fn=8);  // +Y
color("blue")  cylinder(r=0.5, h=25, $fn=8);                        // +Z

Note

When using center=true, notice how the bounding box may show negative coordinates — that’s geometry underground. In a real project, always use translate() to lift centered objects so their bottom is at Z=0.

Build this code and run 3dm info to read the bounding boxes.


Step 2 — Create Your First Project

What a “Project” Is

3dMake organizes work into projects — folders with a specific, standard structure. This structure keeps your source code separate from generated output, which makes it easy to clean, rebuild, back up, and share your work.

Here is what a project folder looks like:

my_project/
  src/          ← your .scad source files live here (YOU write and edit these)
  build/        ← generated STL files go here (3dMake creates these automatically)
  3dmake.toml   ← project configuration file (created when you initialize the project)

Important

Never manually edit files in the build/ folder. Everything in there is generated automatically — changes will be overwritten the next time you run 3dm build. All your actual work goes in src/.

Creating the Project

Linux / macOS (bash):

# Create the project folder and its standard subdirectories
mkdir my_first_project
cd my_first_project
mkdir src build

# Create the main design file
cat > src/main.scad << 'EOF'
// My First Parametric Model
// ========================
// All dimensions in millimeters.
// To customize this design, change the values below and run: 3dm build

width  = 30;   // mm — how wide the box is (X dimension)
depth  = 20;   // mm — how deep the box is (Y dimension, front to back)
height = 10;   // mm — how tall the box is (Z dimension)

cube([width, depth, height]);
EOF

Windows (PowerShell):

# Create project folder and subdirectories
New-Item -ItemType Directory -Path "my_first_project\src","my_first_project\build"
Set-Location "my_first_project"

# Create the main design file
@'
// My First Parametric Model
// All dimensions in millimeters.
// Change values below and run: 3dm build

width  = 30;   // mm
depth  = 20;   // mm
height = 10;   // mm

cube([width, depth, height]);
'@ | Out-File -FilePath "src\main.scad" -Encoding UTF8

Windows (CMD):

mkdir my_first_project\src
mkdir my_first_project\build
cd my_first_project

echo // My First Parametric Model > src\main.scad
echo width  = 30; >> src\main.scad
echo depth  = 20; >> src\main.scad
echo height = 10; >> src\main.scad
echo cube([width, depth, height]); >> src\main.scad

Reading the Code Line by Line

This small file introduces the core pattern you’ll use for the entire course. Let’s read every line carefully.

// My First Parametric Model — this is a comment. In OpenSCAD, anything following // on a line is ignored by the computer — it’s a note for human readers. Comments are essential. They explain what the code does, what the units are, and what you were thinking when you wrote it.

width = 30; — this declares a variable named width and sets it equal to 30. The semicolon at the end is required — it tells OpenSCAD “this statement is finished.” The comment // mm reminds anyone reading the file that this value is in millimeters.

depth = 20; and height = 10; — same pattern. Each variable represents one dimension of the box.

cube([width, depth, height]); — this creates a box. The brackets [] enclose a list of three values: the X size, the Y size, and the Z size. Instead of writing cube([30, 20, 10]) with raw numbers, you use the variable names. This is the magic of parametric design: if you change width = 30 to width = 50 at the top, the cube automatically becomes 50 mm wide everywhere width is used — which might be one place in a simple file, but could be dozens of places in a complex one.

This pattern — declare named parameters at the top of the file, use them in geometry below — is the single most important habit this course will teach you.


Step 3 — Build and Verify

Running Your First Build

With your terminal open inside the my_first_project/ folder, run:

3dm build

This single command does several things: it finds your src/main.scad file, runs OpenSCAD on it to turn the code into geometry, checks the result for basic validity, and saves the output as build/main.stl.

If the build succeeds, you’ll see output indicating the file was written. If there’s an error in your code, you’ll see an error message with a line number pointing to the problem. Error messages with line numbers are extremely helpful — they tell you exactly where to look to fix the issue.

Understanding the Model Information

Now run:

3dm info

This analyzes your built model and prints a report. You’ll see something like this:

File:         build/main.stl
Bounding Box: 30.0 x 20.0 x 10.0 mm
Volume:       6000.0 mm³
Triangles:    12
Description:  A small rectangular box measuring 30mm wide by 20mm deep by 10mm tall.

Let’s understand each piece.

Bounding Box: The bounding box is the smallest rectangular box that perfectly contains your entire model. 30.0 x 20.0 x 10.0 mm means your model is 30 mm in X, 20 mm in Y, and 10 mm in Z. This number is your primary verification tool — if the bounding box doesn’t match what you designed, something went wrong. Check it every single time you build.

Volume: This is how much solid material fills the model. A solid box that is 30 × 20 × 10 mm contains exactly 30 × 20 × 10 = 6,000 cubic millimeters of material. If your model were hollow, the volume would be less. Volume directly predicts how much filament you’ll need.

Triangles: STL files represent surfaces as a mesh of triangles. More triangles means more geometric detail (and a larger file). A simple box needs only 12 triangles. A sphere with smooth curves needs thousands.

Description: The plain-English description comes from an AI analysis of the geometry. It’s useful for a quick sanity check, but it’s not a replacement for checking the bounding box numbers yourself.

Caution

If the bounding box shows 0 × 0 × 0, the build failed and no geometry was produced. Check the output from 3dm build — error messages will point to the specific line in your code.

Estimating Material Cost from Volume

Before printing anything — especially something that might take hours — it’s professional practice to estimate the cost. Here is the formula:

mass (grams) = (volume_mm³ ÷ 1000) × filament_density_g_per_cm³
cost ($)     = mass_g × (spool_price_$ ÷ spool_weight_g)

For our 6,000 mm³ box using PLA filament:

mass = (6000 ÷ 1000) × 1.24 = 7.44 grams
cost = 7.44 × (20 ÷ 1000)   = $0.15

Common filament densities: PLA = 1.24 g/cm³, PETG = 1.27 g/cm³, ABS = 1.05 g/cm³, TPU = 1.20 g/cm³.

This calculation won’t be exact (slicer settings affect actual usage), but it gives you a reasonable estimate within about 20% of the actual cost.


Concept 4: The FDM Printing Pipeline

How Your Code Becomes a Physical Object

Understanding how 3D printing actually works changes how you design. The printing process has physical constraints — things it can and can’t do — and every design decision you make either works with those constraints or fights against them. Here’s the complete journey from your code to a finished print.

Stage 1 — STL File When you run 3dm build, OpenSCAD converts your .scad code into an STL file. STL stands for Standard Triangle Language (sometimes called Standard Tessellation Language). An STL file describes the surface of your 3D model as a mesh of tiny triangles — like wrapping a shape in a piece of paper made of triangles. It contains no color, no material information, no internal structure — just the outer surface geometry.

Stage 2 — Slicing A program called a slicer (PrusaSlicer and Cura are popular options) reads the STL and slices the model into horizontal layers, like cutting through a loaf of bread to see the shape of each slice. The thickness of each slice is the layer height — typically 0.15 to 0.30 mm.

Stage 3 — G-code The slicer converts those layer slices into a file of G-code — a language of machine instructions telling the printer exactly what to do. G-code commands look like: “move the print head to X=50, Y=30; heat the nozzle to 215°C; extrude 2.3 mm of filament.” The printer reads these instructions literally and executes them in sequence.

Stage 4 — Printing The printer reads the G-code and executes it. The nozzle heats to between 200°C and 240°C (depending on the material), melts a thin strand of plastic filament, and deposits it in the shape of each layer — one layer on top of the last, slowly building up the 3D form.

Stage 5 — Cooling and Bonding As each layer is deposited, it needs to cool and bond to the layer below it. This inter-layer fusion is what holds the part together. However, it also means 3D-printed parts are slightly weaker in the vertical direction than in the horizontal direction — because the bond between layers is never quite as strong as the plastic itself. Good design takes this into account: parts that will experience stress should be oriented so the layers are perpendicular to the direction of that stress.

The Three Key Slicer Settings to Know

Layer Height — how thick each printed layer is, typically 0.15 to 0.30 mm. Thinner layers produce smoother surfaces with more detail, but require more layers to reach the same total height, so prints take longer. For most classroom projects, 0.20 mm is a good starting point.

Infill Percentage — the internal structure of a print. A 100% infill print is completely solid. A 0% print is just the outer walls (hollow). In practice, most parts work well at 15–20% infill — the slicer creates a grid-like internal structure that supports the walls without using much material. Structural parts that will bear loads or stress should use 40–50% infill.

Supports — if your design has overhanging geometry (parts that extend horizontally without anything underneath them), the slicer can add temporary scaffolding called supports. These get removed after printing. The problem is that supports can leave rough surfaces and add both print time and material cost. Good design minimizes overhangs, which reduces or eliminates the need for supports.

First Prints Are Tests, Not Final Products

Tip

You will almost never get a perfect-fitting part on the first print. Treat the first print of any new feature as a test print: a quick, small print specifically designed to tell you what needs to be adjusted. This saves time and material by testing deliberately rather than accidentally printing a large part only to find the hole is 0.3 mm too small.


Step 4 — The Edit–Build–Verify Workflow

The Fundamental Loop

Professional software development runs on a tight feedback cycle: write some code, run it, check the result, fix any problems, and repeat. The shorter each cycle is, the faster you learn and the fewer problems pile up. Parametric 3D design works exactly the same way:

EDIT → BUILD → VERIFY → repeat

Edit:   Change src/main.scad in any text editor. Save the file.
Build:  3dm build   → compiles your .scad code into build/main.stl
Verify: 3dm info    → confirms bounding box and volume match your design intent
        (optional)  → open build/main.stl in your slicer for a visual check

Tip

Verify after every meaningful change, not just when you think you’re done. Frequent verification means any problem is always close to the last thing you changed. Verifying only at the end of a long session means sifting through dozens of changes to find one small mistake.

Watch Mode: Automatic Rebuilds

If you’re iterating quickly on a design, you can tell 3dMake to automatically rebuild every time you save your source file:

3dm watch

Run this in one terminal window, keep your text editor open in another. Every time you save src/main.scad, the terminal automatically runs 3dm build and reports the result. This creates a nearly real-time feedback loop: you save the file and, a few seconds later, see whether it built successfully and what the new dimensions are.


Step 5 — Building Parametric Variants

Overriding Parameters at Build Time

Once your design uses variables for all its dimensions, you can generate different versions without editing the source file at all. The -D flag tells OpenSCAD to override a variable at build time:

openscad -D "width=50" -o build/main_wide.stl src/main.scad

This builds a version with width=50 instead of the width=30 in the file — without changing the file. You can combine multiple overrides:

openscad -D "width=50" -D "height=15" -o build/main_large.stl src/main.scad

Building Multiple Variants Automatically

You can use a shell loop to generate a whole family of variants automatically:

Linux / macOS (bash):

>[!TIP]
>Use shell loops to generate multiple parametric variants automatically. Each run creates a separate STL file — a fast way to produce a tolerance test matrix without manually editing the source file.

```bash
# Build four width variants — generates four separate STL files
for w in 20 30 40 50; do
  openscad -D "width=$w" -o "build/main_w${w}.stl" src/main.scad
  echo "Built: width=${w}mm → build/main_w${w}.stl"
done

**Windows (PowerShell):**

```powershell
$widths = @(20, 30, 40, 50)
foreach ($w in $widths) {
  openscad -D "width=$w" -o "build\main_w$w.stl" "src\main.scad"
  Write-Host "Built: width=${w}mm → build\main_w$w.stl"
}

Windows (CMD):

FOR %%W IN (20 30 40 50) DO (
  openscad -D "width=%%W" -o build\main_w%%W.stl src\main.scad
  echo Built width=%%W
)

This is one of the most powerful things about parametric design: one source file, many specific outputs. The file represents the concept; the parameters turn it into instances.


Concept 5: Code Documentation Standards

Why Documented Code Is Part of Certification

When you return to a file weeks later, you will not remember what every variable was for. When a classmate, instructor, or future collaborator reads your code, they need to understand your design intent without asking you. When you submit work for this certification, well-documented code demonstrates professional-level practice — not just that you got the geometry right, but that you thought about it clearly.

OpenSCAD documentation has three levels:

File Header Comments — a block comment at the very top of the file explaining: what this part is, what it’s used for, print recommendations (layer height, infill, supports needed?), and which parameters are meant to be customized. This is the first thing anyone reads.

Parameter Line Comments — every variable declaration should have a comment stating the unit and a reasonable range. This:

wall = 2;   // mm — wall thickness (1.5–3.0 for a 0.4mm nozzle)

is dramatically more useful than just wall = 2;.

Module Comments — every module (a named, reusable chunk of geometry — covered in depth in Lesson 3) should have a one-line description of what shape it creates.

A Well-Documented File Template

// ==============================================================
// Parametric Box Lid
// ==============================================================
// Purpose:     Snap-fit lid for the storage box (box.scad)
// Print time:  ~8 minutes at 0.20 mm layers
// Material:    ~6 g PLA
//
// PARAMETERS TO CUSTOMIZE:
// - box_width:   width of the matching box (default: 60 mm)
// - box_depth:   depth of the matching box (default: 40 mm)
// - lip_height:  how deep the lid lip fits into the box (default: 3 mm)
//
// PRINT RECOMMENDATIONS:
// - Layer height: 0.20 mm
// - Infill:       15%
// - Supports:     not needed
// - Orientation:  print flat, face-down
// ==============================================================

box_width  = 60;   // mm — must match box.scad box_width
box_depth  = 40;   // mm — must match box.scad box_depth
lip_height = 3;    // mm — depth the lid lip extends downward (2–5 mm)
wall       = 2;    // mm — lid wall thickness (1.5–3.0 mm)

// (Geometry below this line — uses the parameters above)

This header comment takes about two minutes to write and saves many minutes of confusion later. Make it a habit starting with your very first project.


Summary Table

ConceptKey Point
Parametric designChange one number, model updates everywhere it’s used
OpenSCADCode-based 3D geometry engine; you describe shapes with text
3dMakeProject manager layer; 3dm build and 3dm info are your main commands
UnitsAlways millimeters — no exceptions
Origin (0,0,0)Front-left corner of build space, at bed level
X axisPoints right
Y axisPoints away from you (back)
Z axisPoints straight up
center=falseDefault — one corner of the object sits at the specified position
center=trueObject straddles the specified position (center is at that point)
3dm buildCompiles src/main.scadbuild/main.stl
3dm infoReports bounding box, volume, triangle count, AI description
3dm watchAuto-rebuilds whenever you save a .scad file
Bounding boxSmallest rectangle containing the whole model — your #1 verification metric
STL fileTriangle-mesh representation of surface geometry
FDM pipelineSTL → Slicer → G-code → Print → Cool
Layer heightThickness of each printed layer; 0.20 mm is a good default
InfillInternal density; 15–20% for typical parts, 40–50% for structural
SupportsTemporary scaffolding for overhangs; minimize them in your design

Extension Resources

Lesson 1 Asset Folder

Learning Series Sample Projects (3dmake_learning_series/)

  • 01_cube_keycap (Beginner) — Text embossing basics
  • 02_parametric_phone_stand (Intermediate) — Transforms and Minkowski fillets
  • 03_stackable_bins (Advanced) — Tolerance and assemblies

Reference Materials (Reference_Materials/)

  • 3dmake-setup-guide.md — Complete setup walkthrough
  • openscad-cheat-sheet.md — Keyboard shortcuts and common functions
  • filament-comparison-table.md — Material properties reference
  • master-rubric.md — Assessment criteria

Quiz — Lesson 1 (15 questions)

  1. What command initializes a 3dMake project?
  2. What folder holds generated STL files?
  3. How do you run 3dMake’s automatic rebuild mode?
  4. Why is it useful to run 3dm build frequently during development rather than only at the end?
  5. Give one reason to prefer an external text editor over the built-in OpenSCAD editor for this workflow.
  6. True or False: 3dMake requires a graphical user interface to use effectively.
  7. Explain what the 3dmake.toml file does in your project.
  8. Describe what the src/ and build/ project folders are used for and which one you edit directly.
  9. In your own words, explain the difference between a visual 3D editor (like Tinkercad) and a code-based parametric design tool (like OpenSCAD). What is the main advantage of the parametric approach?
  10. What validation step should you always perform after running 3dm build before sending a file to print?
  11. If the bounding box reported by 3dm info shows 0 × 0 × 0 mm, what does that tell you, and what should you do next?
  12. Explain what center=false and center=true mean for a cube(). For each, where does the object appear relative to the position you specify?
  13. What does FDM stand for, and what are the five stages of the FDM pipeline from STL file to cooled physical part?
  14. A box has dimensions 50 × 40 × 25 mm and you’re printing it in PLA (density 1.24 g/cm³) at 100% infill. Using a $22 / 1 kg spool, what is the estimated material cost? Show your calculation.
  15. You run 3dm build and receive the error “No such file or directory: src/main.scad”. List two likely causes and the fix for each.

Extension Problems (15)

  1. Add a README entry explaining your top-level parameters and expected units.
  2. Create a parameter variant by changing width by 20% and build both variants; compare dimensions using 3dm info to confirm the change.
  3. Script a command sequence that automates the entire new-project setup: create folder, create src/main.scad, and run 3dm build — in a single script file.
  4. Intentionally introduce a syntax error in your .scad file (remove a semicolon), run 3dm build, and document what the error message says and which line it points to. Then fix it.
  5. Prepare a short instructor sign-off checklist describing the safety checks you should complete before sending a file to print.
  6. Build a variant testing suite: create 5 different combinations of width, depth, and height, build all five, and record the bounding box and volume for each.
  7. Create a 3dMake project template with best-practice structure, documentation header, and parameter comments. Write a README explaining how to use it.
  8. Write a short accessibility guide explaining how a student using a screen reader could use 3dm info output to understand a model’s geometry without a visual preview.
  9. Design a simple parametric part library (three or more related parts) in a single project. Document all parameters with units and example values.
  10. Write a comprehensive troubleshooting guide for common 3dm build errors, with the cause and fix for each.
  11. Add a .gitignore file to your project, commit it using Git, make a parameter change and create a second commit. In 2–3 sentences, explain why version control is valuable for parametric design.
  12. Edit the global configuration file using 3dm edit-global-config to change the default editor. Document the setting name and how you verified the change took effect.
  13. Create a project with three .scad source files and build each using 3dm build -m <n>. Record the output STL filenames.
  14. Research the FDM layer height trade-off: slice the same model at 0.15 mm, 0.20 mm, and 0.30 mm. Record the estimated print time and filament use for each. What is the trade-off?
  15. Write a one-page “new student onboarding guide” for 3dMake covering installation, project creation, first build, and first print. Write it as if your audience is a classmate who has never used the command line.

References and Helpful Resources

  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake

  • OpenSCAD Manual — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual

  • OpenSCAD Parametric Design — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Variables

  • OpenSCAD Review — CadHub — https://learn.cadhub.xyz/blog/openscad-review/

  • PrusaSlicer Validation Tools — https://docs.prusa3d.com/en/guide/39012-validation-tools/

  • 3dmake e2e_test.py — https://github.com/tdeck/3dmake/blob/main/e2e_test.py

  • PrusaSlicer Documentation — https://docs.prusa3d.com/en/

  • OpenSCAD Non-Manifold FAQ — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/FAQ#Why_is_my_model_not_manifold.3F

Supplemental Resources

  • Programming with OpenSCAD EPUB Textbook — assets/Programming_with_OpenSCAD.epub
  • CodeSolutions Repository — https://github.com/ProgrammingWithOpenSCAD/CodeSolutions
  • OpenSCAD Quick Reference — https://programmingwithopenscad.github.io/quick-reference.html
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Extension Project and Reference Appendices

All supporting documents for Lesson 1 are included below. You do not need to open any additional files.


Appendix A: Your First Print — Extension Project

Estimated time: 2–4 hours (including setup and print monitoring)

Overview

This extension project applies the workflow and concepts from Lesson 1 to a real physical print. Rather than designing from scratch, you’ll select a simple ready-made model, evaluate whether it’s appropriate for a beginner print, configure slicer settings, run the print safely, and document what happened. The goal is to complete one full cycle of the pipeline you just learned — from file to printed object — and to practice the observation and documentation habits you’ll use for every print in this course.

Learning Objectives

By completing this project, you will:

  • Select a simple ready-made model and evaluate its printability for a classroom printer
  • Configure slicer settings for a short-duration print and prepare the printer safely
  • Monitor a print in progress and recognize early warning signs of failure
  • Document print parameters and reflect on the physical outcome

Materials

  • Computer with slicer and access to an online model repository
  • Classroom-approved printer, filament spool

Tasks

  1. Choose a simple model (under 2 hours estimated print time) from Thingiverse or Printables. Download the STL.

  2. Inspect the model before loading it in the slicer. Look at it from all angles. Note any overhangs, thin features, or very small details. Write two short reasons why this model is appropriate for a first print — specifically, why it is not risky.

  3. Load the model in your slicer, select the classroom profile, and adjust settings only if necessary. Record the final print time estimate, layer height, infill %, and filament weight estimate.

  4. Perform safety checks using the checklist in Lesson 5 Appendix A (or the condensed checklist below). Start the print and remain present and watching for the first 15 minutes. Note what you observe about first-layer adhesion and extrusion quality.

  5. After the print cools, measure three critical dimensions using calipers (or by comparing against the model’s stated dimensions). Record the measured values and any deviations.

Condensed Pre-Print Safety Checklist

  • Bed clean and level
  • Filament loaded and extruding cleanly (run a short purge)
  • Build area clear of obstructions
  • Print area free of flammable materials
  • You will remain present for the first 15 minutes

Probing Questions

  1. Why did you select this model? What specific risks did you anticipate, and how does this model avoid or minimize them?
  2. Which slicer setting most affects print time for this model, and why?
  3. If a thin feature failed during printing, what is the minimum change you would make to give it a better chance on the next attempt?

Starter Code

If you want to build a simple printable object from scratch rather than downloading one, use this scaffold as your starting point:

// Basic Project Scaffold
// ============================================
// PROJECT CONFIGURATION
// ============================================
// Set your project dimensions here. All other geometry derives from these.

object_w  = 50;   // mm — overall width
object_d  = 50;   // mm — overall depth
object_h  = 20;   // mm — overall height
wall      = 2.0;  // mm — wall thickness (2–3mm recommended for FDM)
$fn       = 30;   // curve resolution (higher = smoother, slower to render)

// ============================================
// MAIN DESIGN
// ============================================

module base_shape() {
  // Replace this cube with your own geometry
  cube([object_w, object_d, object_h]);
}

module hollow_version() {
  // Creates a hollow version by removing an inner volume
  difference() {
    base_shape();
    translate([wall, wall, wall])
      cube([object_w - 2*wall,
            object_d - 2*wall,
            object_h]);  // open top — no overhang needed
  }
}

// Render your design:
hollow_version();

Deliverables

  • Short report: model selected, key slicer settings, measured dimensions and deviations, answers to probing questions
  • Photos of the final print (at least two angles)
  • Completed student documentation template (Appendix B)

Appendix B: Your First Print — Student Documentation Template

Author: ________________ Date: __________ Description: Select a simple 3D model, configure slicer settings, and complete your first independent print job.


Model Selection

  • Model name and source (Thingiverse, Printables, etc.):
  • Link or file name:
  • Why did you choose this model?
  • Why is this model appropriate for a first print (two specific reasons)?

Printability Assessment

  • Estimated print time (from slicer): ____ hours ____ min
  • Estimated filament: ____ g
  • Layer height selected: ____ mm
  • Infill %: ____
  • Supports required? Yes / No — if yes, describe where:
  • Any overhangs or thin features that concerned you?

Printer Setup Log

ParameterValue
Printer model
Nozzle diametermm
Nozzle temperature°C
Bed temperature°C
Layer heightmm
Infill %
Support settings
Print speedmm/s

Safety Checks

  • Bed clean and level
  • Filament loaded and purged cleanly
  • Nozzle at correct first-layer height
  • Print area clear of obstructions
  • I remained present and watching for the first 15 minutes

  • What did you observe in the first layer?
  • Was first-layer adhesion good, marginal, or poor?
  • Any extrusion issues observed (clicking, skipping, thin lines)?
  • Print completed successfully? Yes / No / Partially
  • If partially or no — what happened and at what layer?

Dimensional Verification (After Cooling)

Measure three features on the printed part and compare to the model’s stated dimensions:

FeatureModel Spec (mm)Measured (mm)Deviation (mm)Notes

Reflections

What went well:

What didn’t go well:

What would you do differently next time:

If you printed this again, what settings would you change and why?


Attachments Checklist

  • STL file or link to source model
  • Slicer settings (screenshot or exported settings file)
  • Photo of final print — at least two angles
  • Completed measurement table above
  • Answers to probing questions

Teacher Feedback

CategoryScore (0–3)Notes
Problem & Solution — appropriate model selected; print completed
Setup & Documentation — printer setup log complete; safety checks done
Reflection — measurements recorded; reflection is specific and shows learning
Total (0–9)

Resubmission: If resubmitting, attach a paragraph explaining what was changed and why. The resubmission score replaces the original.


Appendix C: Your First Print — Instructor Reference

Project Context

This is the first physical print extension project in the course. Its primary purpose is to establish safe printer operation habits and complete documentation practices — not to produce a complex or impressive object. A student who selects an appropriate model, monitors the print safely, and documents the outcome accurately has succeeded, regardless of whether the print is visually impressive.

Key Learning Points to Reinforce

Model selection discipline. The most common mistake at this stage is selecting a model that is too complex, too large, or has features that will fail (overhangs without supports, very thin walls, very fine detail). Push students to justify their selection in terms of printability, not just aesthetics.

Important

The first 15 minutes rule: students must stay and watch the printer for the first 15 minutes of every print. A print that lifts off the bed in the first few layers becomes a tangled failure — you must be present to catch it early.

Documentation enables iteration. A student who records their slicer settings has something to start from on the next print. A student who doesn’t has to guess. Reinforce this constantly.

Constraints (Enforce These)

  • Model must be under 2 hours estimated print time
  • Minimal or no support requirements recommended
  • Student must record slicer settings, not just print the file
  • Dimensional measurements must be taken after the part has fully cooled

Assessment Notes

Strong submissions show: clear model selection reasoning (not just “it looked cool”), a complete printer setup log, specific first-layer observations, measurements that reflect actual caliper readings (not round numbers), and a reflection that identifies something specific to do differently.

Common weak areas: Vague reflections (“it went well”), missing measurements, and skipped safety checks. Address all three in feedback.


Appendix D: 3dMake Setup and Workflow Guide

Installing 3dMake

Prerequisites

Before installing 3dMake, you need:

  • Node.js version 18 or higher — download from https://nodejs.org
  • OpenSCAD — download from https://openscad.org/downloads.html

To verify both are installed, open a terminal (PowerShell on Windows, Terminal on macOS/Linux) and run:

node --version    # should print v18.0.0 or higher
openscad --version  # should print a version number

If either command returns “not found,” install that software first before continuing.

Installing 3dMake

npm install -g 3dmake

Verify the installation:

3dm --version

You should see a version number. If you get “command not found,” check that npm’s global bin directory is in your PATH (see Troubleshooting below).


Creating Your First Project

# Create a new folder for your project and enter it
mkdir my_project
cd my_project

# Initialize a 3dMake project
3dm init

3dm init creates this project structure:

my_project/
├── src/
│   └── main.scad      ← Your design code goes here
├── build/             ← Generated STL files appear here (auto-created)
└── 3dmake.toml        ← Project configuration

The src/ folder is where you write your OpenSCAD code. You should never need to edit files in build/ directly — that folder is managed by 3dMake.

3dmake.toml stores your project settings: the slicer path, filament density, cost-per-gram, and other project-level configuration. Open it with any text editor to see the available settings.


The Core Workflow

Every design session follows this cycle:

edit src/main.scad  →  3dm build  →  3dm info  →  review / repeat

3dm build — compiles your .scad source into an STL file in the build/ folder.

3dm build              # standard build
3dm build --clean      # delete build/ first, then rebuild
3dm build --watch      # auto-rebuild whenever you save src/main.scad

3dm info — reports on the most recently built STL: bounding box, volume, triangle count, and an AI-generated description.

3dm info
3dm info --view front
3dm info --view top,front,isometric

3dm preview — renders an image of your model to build/preview.png.

3dm orient — recommends a print orientation based on your model’s geometry.

3dm slice — calls your configured slicer on the current STL.


Command Reference

CommandPurposeNotes
3dm initInitialize a new projectRun once per project
3dm buildCompile source → STLRun after every code change
3dm infoReport dimensions and AI descriptionAlways run before sending to print
3dm previewRender model imageUse for quick visual check
3dm orientAI print orientation suggestionUse as a starting point, verify yourself
3dm sliceRun slicer on current buildRequires slicer path in 3dmake.toml
3dm edit-global-configEdit the global settings fileFor changing default editor, slicer path

Configuring Your Slicer

Edit 3dmake.toml in your project folder and add your slicer path:

Windows (PrusaSlicer):

[slicer]
path = "C:/Program Files/Prusa3D/PrusaSlicer/prusa-slicer.exe"

macOS (PrusaSlicer):

[slicer]
path = "/Applications/PrusaSlicer.app/Contents/MacOS/PrusaSlicer"

Linux:

[slicer]
path = "/usr/bin/prusa-slicer"

Configuring Cost Estimation

To use the cost estimation feature, set your filament density and spool price:

[filament]
density = 1.24        # g/cm³ — PLA default (see Lesson 5 Appendix C for other materials)
spool_weight = 1000   # grams per spool
spool_price = 22.00   # dollars per spool

3dMake will then include cost estimates in 3dm info output.


Troubleshooting

3dm: command not found after installation

npm’s global bin directory isn’t in your PATH. Find the directory:

npm config get prefix

Add the bin subdirectory of that path to your PATH. On Windows, this is usually C:\Users\YourName\AppData\Roaming\npm. On macOS/Linux, it’s usually ~/.npm-global/bin or /usr/local/bin.

No such file or directory: src/main.scad

You either haven’t run 3dm init, or you’re in the wrong folder. Run pwd to confirm your current location, and ls (or dir on Windows) to see if src/ exists.

OpenSCAD: command not found during build

OpenSCAD isn’t in your PATH. On Windows, find where OpenSCAD is installed (usually C:\Program Files\OpenSCAD\) and add it to your PATH in System Settings → Environment Variables.

Build succeeds but 3dm info shows 0 × 0 × 0 mm

Your OpenSCAD code compiled without errors but produced no geometry. Check that your shapes are actually being rendered (not commented out), and that no difference() has subtracted more than it started with.

WARNING: Normalized tree is empty

Same as above from OpenSCAD’s perspective. The most common causes: a shape with zero volume, all geometry inside a difference() was subtracted away, or a module was defined but never called.


Appendix E: Navigating This Curriculum (mdBook Guide)

This curriculum is published as a web book using mdBook. This guide explains how to find what you need, navigate between chapters, and use the book with a screen reader.

Basic Navigation

Sidebar table of contents — the left side of the page lists all chapters by unit and lesson. Click or tap any title to jump to it. On a small screen, the sidebar may be hidden — look for a hamburger menu icon (three horizontal lines) to show it.

Arrow navigation — at the bottom of every page are Previous and Next links. You can also use keyboard arrow keys:

  • Left Arrow — go to the previous chapter
  • Right Arrow — go to the next chapter

Search — press S to open the search box. Type your search term; results appear as a dropdown. Click any result to jump to that chapter. Press Escape to close search.

KeyAction
SFocus the search box
EscapeClose search results
Left ArrowPrevious chapter
Right ArrowNext chapter
TToggle the table of contents sidebar

Screen Reader Navigation

  • H — jump between headings; the fastest way to skim a long lesson
  • D — move between landmark regions (use to reach the sidebar)
  • NVDA + F7 — open the Elements List; select “Landmarks” to navigate to the sidebar directly
  • Set punctuation level to Most or All before reading code blocks: NVDA + P to cycle
  • Ctrl + F — browser Find, works alongside mdBook search
  • H — jump between headings
  • R — move between landmark regions to reach the sidebar
  • JAWS Key + F6 — list all headings on the current page
  • Set punctuation to All before reading code: JAWS Key + Shift + 2
  • JAWS Key + F5 — links list
  • Ctrl + F — browser find

With VoiceOver (Mac / iOS)

  • VO + U — open the rotor; select Headings to navigate by heading
  • H (Quick Nav on) — move between headings
  • iOS: use the rotor (two-finger rotate) to set navigation mode to Headings

Finding What You Need

If you know the unit or project: open the table of contents and look for the unit name. Structure: Unit 0 (Foundation lessons) → Unit 1 (Guided projects) → Unit 2 (Intermediate skills) → Unit 3 (Open-ended projects) → Reference Materials.

If you’re looking for a specific term or command: use Search (S). Search for an OpenSCAD command (difference, translate), a vocabulary word (infill, tolerance), or a project name.

While working: keep a second browser tab open to the Reference Materials section. Useful pages to bookmark: OpenSCAD Cheat Sheet, Slicing Settings Quick Reference, Filament Comparison Table, Screen Reader Coding Tips.


Appendix F: Screen Reader Coding Tips (NVDA and JAWS)

General Principles

Turn punctuation up. All OpenSCAD syntax — semicolons, brackets, parentheses, commas — is meaningful. If your screen reader skips punctuation, you will miss syntax errors. Set to Most or All before coding.

Navigate by line. Arrow up and down through code one line at a time. Use Ctrl + Left/Right to move word by word within a line.

Use go-to-line. OpenSCAD errors always give a line number. In VSCode: Ctrl + G, type the number, press Enter.

Comment as you go. A short comment after a block of code lets you navigate back to it by searching with Ctrl + F.


NVDA Quick Reference

Setting punctuation level: NVDA + P cycles through None → Some → Most → All. For code: Most or All.

ActionKeys
Read current lineNVDA + Up Arrow
Spell current lineNVDA + Up Arrow (twice quickly)
Read from cursorNVDA + Down Arrow
Read current wordNVDA + Numpad 5
Spell current wordNVDA + Numpad 5 (twice quickly)
Stop readingCtrl

Navigation in VSCode with NVDA:

ActionKeys
Move by characterLeft / Right Arrow
Move by wordCtrl + Left / Right Arrow
Move by lineUp / Down Arrow
Start / end of lineHome / End
Go to line numberCtrl + G, type number, Enter
Find textCtrl + F
Toggle line commentCtrl + /

If NVDA stops reading the editor: press NVDA + Space to toggle between Browse and Application mode. For code editors, you want Application mode.


JAWS Quick Reference

Setting punctuation level: JAWS Key + Shift + 2 cycles through levels. For code: All.

ActionKeys
Read current lineJAWS Key + Up Arrow
Spell current lineJAWS Key + Up Arrow (twice quickly)
Read from cursorJAWS Key + A
Read current wordJAWS Key + Numpad 5
Stop readingCtrl
Increase speech rateAlt + Ctrl + Page Up
Decrease speech rateAlt + Ctrl + Page Down

Navigation in VSCode with JAWS:

ActionKeys
Move by characterLeft / Right Arrow
Move by wordCtrl + Left / Right Arrow
Move by lineUp / Down Arrow
Go to line numberCtrl + G
Find textCtrl + F
Toggle commentCtrl + /

If JAWS stops reading the editor: press JAWS Key + Z to toggle Virtual mode off. You want Virtual mode OFF in VSCode.


OpenSCAD-Specific Tips

Reading errors. OpenSCAD errors always include a line number. Use Ctrl + G in VSCode to jump to it. Common errors:

Error messageWhat it usually means
Expected ';' ...Missing semicolon at end of a statement
Expected ',' or ')' ...Missing comma between parameters, or unclosed parenthesis
Identifier ... is undefinedVariable name typed wrong, or used before declaration
WARNING: Normalized tree is emptyShape has no geometry — subtracted more than you started with

Bracket matching. Every ( needs a ), every [ needs a ], every { needs a }. In VSCode, cursor on a bracket highlights its match. Navigate to the matching bracket with Ctrl + Shift + \.

Commenting out code. To test without deleting: // before a line, or Ctrl + / in VSCode to toggle comment on selected lines.


Caliper and OpenSCAD Workflow Tip

When measuring and entering into OpenSCAD: say the measurement aloud before typing, then read it back after typing to confirm.

  1. Measure → say “seventy point three millimeters”
  2. Type 70.3 in OpenSCAD
  3. Read back: “seven zero point three” — confirm match

Appendix G: VSCode Setup Guide for NVDA and JAWS

Why VSCode Instead of the OpenSCAD Editor

The built-in OpenSCAD editor has inconsistent behavior with screen readers — focus can jump unexpectedly and the editor sometimes stops being read after certain actions. VSCode is a mainstream code editor with strong, well-tested accessibility support for both NVDA and JAWS.

You write code in VSCode. OpenSCAD runs in the background to render the preview. You never need to interact with the OpenSCAD editor itself.


Install Required Software

Install VSCode — download from https://code.visualstudio.com/ During installation: check “Add to PATH” and “Register Code as an editor for supported file types.”

Install OpenSCAD — download from https://openscad.org/downloads.html Use the installer version (not portable). After installing, verify it’s in your PATH:

openscad --version

Optional: OpenSCAD VSCode Extension — press Ctrl + Shift + X, search for “OpenSCAD Language Support,” install it. Adds syntax highlighting and keyword completion for .scad files.


Configure the Task Runner

The task runner lets you open your .scad file in OpenSCAD or export an STL with a single keypress.

Create or open your workspace folder in VSCode:

cd ~/Documents/OpenSCAD_Projects
code .

Create tasks.json:

  1. Press Ctrl + Shift + P to open the Command Palette
  2. Type Tasks: Configure Task and press Enter
  3. Select “Create tasks.json file from template” → “Others”

Replace the file’s entire contents with:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Preview in OpenSCAD",
      "type": "shell",
      "command": "openscad",
      "args": ["${file}"],
      "group": { "kind": "build", "isDefault": true },
      "presentation": { "reveal": "silent", "panel": "shared" },
      "problemMatcher": []
    },
    {
      "label": "Export STL",
      "type": "shell",
      "command": "openscad",
      "args": [
        "-o",
        "${fileDirname}/${fileBasenameNoExtension}.stl",
        "${file}"
      ],
      "group": "build",
      "presentation": { "reveal": "always", "panel": "shared" },
      "problemMatcher": []
    }
  ]
}

Save with Ctrl + S.

Run the preview: with a .scad file open, press Ctrl + Shift + B. OpenSCAD opens and displays your model. Alt + Tab to return to VSCode.

Export STL: Ctrl + Shift + P → “Tasks: Run Task” → “Export STL.”


NVDA Settings for VSCode

  • Symbol level: Most (NVDA + N → Preferences → Settings → Speech → Symbol level: Most)
  • For code reading: NVDA + P to cycle to Most or All on the fly

JAWS Settings for VSCode

  • Toggle Virtual mode OFF: JAWS Key + Z (you want Virtual mode off in VSCode)
  • Punctuation level: All (JAWS Key + Shift + 2)

Workflow Summary

1. Open VSCode workspace          code ~/Documents/OpenSCAD_Projects
2. Open or create a .scad file    Ctrl + P → type filename
3. Write OpenSCAD code
4. Preview in OpenSCAD            Ctrl + Shift + B
5. Export STL                     Ctrl + Shift + P → Tasks: Run Task → Export STL
6. Open slicer, import STL, slice, export G-code
7. Print

Troubleshooting

ProblemSolution
OpenSCAD doesn’t openConfirm openscad --version works in PowerShell
VSCode not read by screen readerJAWS: press JAWS Key + Z to exit Virtual mode; NVDA: click inside the editor once to confirm focus
Can’t find error in codeError includes a line number — use Ctrl + G to jump to it
.scad has an errorAlt + Tab to OpenSCAD to read the console; arrow through the error message
-e

Lesson 2 — Geometric Primitives and Constructive Solid Geometry

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

In Lesson 1, you made a box by calling cube(). You understood the coordinate system, installed the tools, and ran the complete build-verify workflow. That’s a real foundation — but a single rectangular box isn’t going to take you very far as a designer.

This lesson introduces the complete vocabulary of 3D shapes OpenSCAD knows how to build, and — more importantly — the three operations that let you combine those shapes into virtually anything you can imagine. Those three operations are union (merge), difference (subtract), and intersection (keep only what overlaps). Together with the primitive shapes, they form a system called Constructive Solid Geometry, and nearly every 3D model ever built in OpenSCAD is made from these tools.


Learning Objectives

By the end of this lesson you will be able to:

  • Use all core OpenSCAD 3D primitives: cube, sphere, cylinder, polygon
  • Combine shapes with union(), difference(), and intersection()
  • Apply the 0.001 mm offset rule and understand exactly why it exists
  • Create 2D profiles with polygon() and extrude them into 3D geometry
  • Use rotate_extrude() and linear_extrude() to create complex rotational shapes
  • Use the four debugging modifier characters (#, %, !, *)
  • Use hull() to create convex envelope shapes

Concept 1: What Are Primitives?

The Raw Materials of 3D Design

A primitive is the simplest, most basic shape a system can produce from scratch, with no prior shape as input. Everything more complex gets built by combining and modifying these primitives. Think of them the way a sculptor thinks about blocks of material: the primitive is the raw material, and the operations you’ll learn in this lesson are the tools you use to shape it.

OpenSCAD has four main 3D primitives. Every complex shape you’ll ever design in this course is built from some combination of these four, using the CSG operations to combine them.


Step 1 — The Four Core 3D Primitives

cube([width, depth, height]) — The Rectangular Box

Despite the name cube, this primitive creates any rectangular box — it doesn’t have to be a perfect cube. The three numbers you provide are the dimensions along the X, Y, and Z axes respectively. cube([30, 20, 10]) creates a box that is 30 mm wide (X), 20 mm deep (Y), and 10 mm tall (Z).

The center=true option (which you learned about in Lesson 1) centers the box on the origin rather than placing one corner there. Remember: center=false is the default, and it’s usually what you want for parts that should sit on the build plate.

sphere(r=radius) — The Round Ball

sphere(r=10) creates a sphere with a 10 mm radius (so 20 mm diameter). The sphere is centered on the origin by default — it can’t be un-centered the way a cube can.

The key parameter to know here is $fn — short for “facet number.” OpenSCAD doesn’t have a mathematically perfect curved surface; it approximates curves by using lots of flat faces. A sphere with $fn=8 looks like a faceted gem. A sphere with $fn=64 looks smooth and round. The catch is that higher $fn values take longer to compute. During development, use $fn=16 for speed. Use $fn=64 or higher only when you’re generating your final print file. Many designers set $fn globally at the top of their file.

cylinder(h=height, r=radius) — The Tube, Cone, or Pipe

cylinder(h=20, r=8) creates a 20 mm tall cylinder with an 8 mm radius. Like spheres, $fn controls how round it looks.

There’s an especially powerful variant: instead of a single r (which makes both the top and bottom the same radius), you can specify r1 for the bottom radius and r2 for the top radius. This creates tapered shapes:

  • r1=10, r2=5 creates a cone that’s wider at the bottom and narrower at the top
  • r1=8, r2=0 creates a spike — the top radius is zero, so the top comes to a point
  • r1=0, r2=8 creates an upside-down spike — a shape that tapers to a point at the bottom

This flexibility makes cylinder far more versatile than its name suggests.

polygon(points) — The Custom 2D Shape

None of the above shapes can make an L-shape, a T-shape, a hexagon, or a star. That’s what polygon() is for.

polygon() accepts a list of (x, y) coordinate pairs and creates a flat 2D shape in the XY plane by connecting them in order. The shape automatically closes — the last point connects back to the first. Points should be listed in counterclockwise order as seen from above — this convention tells OpenSCAD which side is the “inside” of the polygon.

By itself, a polygon() is a flat 2D cutout. Combined with linear_extrude(height=N), it gets pushed straight up along the Z axis to become a 3D prism with that polygon as its cross-section. This is your escape hatch for any shape that can’t be described with boxes, spheres, and cylinders.

// All four primitives demonstrated:

// 1. A simple box (already familiar from Lesson 1)
cube([30, 20, 10]);

// 2. A sphere — note it's centered on origin by default
// Translate it sideways so it doesn't overlap the cube
translate([40, 0, 10])
  sphere(r=10, $fn=32);    // $fn=32 gives a smooth appearance

// 3. A standard cylinder
translate([70, 0, 0])
  cylinder(h=20, r=8, $fn=32);

// 4. A tapered cylinder (cone) — wider at the bottom
translate([100, 0, 0])
  cylinder(h=20, r1=10, r2=3, $fn=32);

// 5. A spike — r2=0 makes a pointed top
translate([130, 0, 0])
  cylinder(h=20, r1=8, r2=0, $fn=32);

// 6. A polygon extruded into a prism
// This L-shape profile gets pushed up 5 mm to become a 3D L-bracket
translate([0, 40, 0])
  linear_extrude(height=5)
    polygon([[0,0],[40,0],[40,8],[8,8],[8,30],[0,30]]);

After building this code, run 3dm info to check the bounding box of each shape and make sure you understand the relationship between the numbers you typed and the dimensions reported.


Concept 2: Constructive Solid Geometry

The Logic Behind Combining Shapes

Constructive Solid Geometry (CSG) is a technique for building complex 3D shapes by performing logical operations on simpler ones. The word “Boolean” comes from Boolean algebra — the mathematics of true/false logic. In 3D space, a Boolean operation asks a question about every point in space: is this point inside shape A? Inside shape B? Inside both? Inside neither?

The three answers to those questions correspond to the three CSG operations.

Why This Approach Is So Powerful

Think about how you’d make a box with a cylindrical hole drilled through it. You can’t do that with a single primitive. But you can:

  1. Create a box
  2. Create a cylinder the size of the hole
  3. Subtract the cylinder from the box

That’s difference(). Most real-world parts are designed exactly this way: start with a basic solid shape, then cut, drill, and hollow it using additional shapes as “tools.”

Now think about a phone stand that has a rounded edge. You can’t describe that with a box. But you can:

  1. Create the main body as a box
  2. Create a sphere slightly larger than the corner radius
  3. Use hull() to create a smooth, rounded version

That’s the power of CSG: you’re building a vocabulary of operations that let you describe arbitrarily complex geometry by combining simple pieces.


Step 2 — The Three CSG Operations

union() — Merge Shapes Together

union() combines two or more shapes into a single solid. Any point that is inside any of the shapes is inside the result.

An important subtlety: union() isn’t the same as just rendering two objects next to each other. If shapes overlap, union() properly merges them into a single watertight solid. Two overlapping objects without a CSG wrapper can cause problems for the slicer — it may not know whether the overlapping region should be treated as solid once or twice. Always use union() when shapes share space.

// union() — combines a cube and a sphere into one solid piece
// The sphere sits on top of the cube, and the two are fused where they meet.
union() {
  cube([20, 20, 5]);
  translate([10, 10, 5])
    sphere(r=10, $fn=32);
}

Build this and notice: the cube and sphere are one object. You can’t select them separately.

difference() — Subtract Shapes

difference() subtracts child shapes from the first child. The first shape listed inside difference() is the base — the “workpiece.” Every shape listed after it acts as a cutting tool, removing its volume from the base.

Think of a drill press: the block of material is the first child, and the drill bits are the shapes that follow. You position the drills where you want the holes, and difference() removes exactly the volume each drill bit occupies.

// difference() — a cube with a cylindrical hole drilled through it
// The cube is the base. The cylinder is the cutting tool.
difference() {
  cube([20, 20, 20]);
  translate([10, 10, -0.001])       // see Step 4 for why this -0.001 matters
    cylinder(h=20.002, r=5, $fn=32);
}

Caution

The most common mistake with difference() is accidentally listing the cutting tool first and the base second — the result will be empty or backwards. Always check: is the first child in your difference() the piece you want to keep?

intersection() — Keep Only What Overlaps

intersection() keeps only the volume that exists inside all shapes simultaneously. If shape A and shape B overlap, intersection() gives you just the overlapping region — everything that is inside both at the same time.

A practical mental model: intersection() is like a cookie cutter. The cookie cutter shape is one child, the dough is another. The result is the piece of dough within the cutter’s outline.

// intersection() — keeps only the region inside both shapes
// A cube intersected with a sphere = a cube with rounded corners
intersection() {
  cube([20, 20, 20], center=true);
  sphere(r=12, $fn=64);
}

Build this and observe: the straight edges of the cube are rounded off wherever the sphere’s surface cuts through them. The result is a shape that’s simultaneously box-like and rounded.

Visualizing Each Operation

The best way to internalize these operations is to build each example above separately and study the result before moving on. When you can predict what each operation will produce before you build it, you’re ready to combine them in more complex designs.

Here’s a quick mental checklist:

  • union(): Think “merge everything together, fill in any gaps.”
  • difference(): Think “start with the first thing, carve away everything else.”
  • intersection(): Think “keep only the parts that are inside every single child.”

Step 3 — polygon() for Custom 2D Profiles

When Primitives Aren’t the Right Shape

Boxes, spheres, and cylinders get you surprisingly far. But eventually you’ll need a shape that doesn’t fit any of them — an L-bracket, a triangular wedge, a hexagonal base, an irregular outline traced from a measurement. That’s where polygon() earns its place.

polygon() takes a list of (x, y) coordinate pairs and creates the 2D shape enclosed by connecting them in order. The shape is drawn in the XY plane. Because it’s 2D, you can’t print it directly — but combined with linear_extrude(height=N), it becomes a 3D solid with that exact cross-section.

Here’s how to use it: sketch your cross-section shape on graph paper. Mark the coordinates of every corner. Transfer those coordinates into the polygon() list. Connect the last point back to the first (OpenSCAD does this automatically). List them counterclockwise when viewed from above.

// An L-shaped bracket: cross-section traced from corner coordinates
bracket_profile = [
  [0,  0],    // bottom-left
  [40, 0],    // bottom-right
  [40, 8],    // step up — beginning of horizontal arm's top edge
  [8,  8],    // inside corner of the L
  [8,  30],   // top of the vertical arm
  [0,  30]    // top-left
];

// Extrude 5 mm along Z — this produces a 3D L-bracket
linear_extrude(height=5)
  polygon(bracket_profile);

Walk through those coordinates: starting at the bottom-left, moving right along the bottom, up and left to form the horizontal arm, then up the vertical arm, and back to the start. The result is a shape you genuinely cannot make with cube() alone.

The graph-paper method works for almost any traced shape. Measure your object, draw it on grid paper, read off the corner coordinates, and type them in. This is a real engineering workflow.


Step 4 — The 0.001 mm Offset Rule

The Co-Planar Face Problem

When you use difference() to cut one shape with another, there’s a subtle problem that occurs when the cutting shape shares an exact face with the base shape — for example, when the bottom face of a cutting cylinder sits at exactly Z=0, the same as the bottom face of the box it’s cutting.

At that shared boundary, OpenSCAD faces an ambiguity: does this face belong to the outer solid or the inner (cutting) solid? The geometry engine can’t make that decision cleanly, and the result is undefined behavior — sometimes a rendering artifact, sometimes a non-manifold edge that crashes the slicer, sometimes output that looks fine in preview but is broken in the exported STL.

This problem is called a co-planar face problem, and it’s one of the most common sources of mysterious errors in OpenSCAD files.

The Fix

Important

The 0.001 mm offset rule: whenever subtracting a shape, extend the cutting shape 0.001 mm past each face it needs to pass through (0.002 mm total extra length). This eliminates co-planar face ambiguity that causes rendering artifacts and slicer errors.

Specifically, move it 0.001 mm past the face on the entry side and make it 0.002 mm longer total.

Why 0.001 mm? It’s large enough to eliminate the ambiguity entirely — the cutting shape now unambiguously passes through the surface. It’s also small enough that no printer in the world can detect it. The 0.001 mm offset is invisible in the physical print.

// WRONG — co-planar faces: the cutting shape is exactly as tall as the base
// This may produce rendering artifacts or slicer errors.
difference() {
  cube([20, 20, 10]);
  translate([1, 1, 0])      // cutting shape's bottom at Z=0, same as base
    cube([18, 18, 10]);     // cutting shape's top at Z=10, same as base's top
}

// CORRECT — the 0.001 offset rule applied
// The cutting shape starts 0.001 mm BELOW the base bottom
// and extends 0.001 mm ABOVE the base top.
difference() {
  cube([20, 20, 10]);
  translate([1, 1, -0.001])         // start 0.001 mm below the floor
    cube([18, 18, 10 + 0.002]);     // 0.001 below + 0.001 above = 0.002 extra height
}

The pattern to memorize: when cutting along the Z axis, use translate([x, y, -0.001]) to start the cut 0.001 mm below the floor, and add 0.002 to the cutting shape’s height (0.001 below + 0.001 above = 0.002 total extra). For cuts along the X or Y axis, apply the same logic to those dimensions instead.


Step 5 — Debugging Modifier Characters

The Four Special Modifiers

OpenSCAD provides four modifier characters that you can prefix onto any shape to temporarily change how it appears in the preview. These are debugging tools — they don’t change the final exported geometry. Always remove them before exporting a file for printing.

# (hash / highlight) — renders the shape in translucent pink/red, and keeps it in the model. Use this when you want to see exactly where a cutting shape is sitting relative to the base. Add # to a cylinder inside a difference() and you’ll see the cutting tool highlighted.

% (percent / ghost) — renders the shape as a transparent ghost, and excludes it from the model output. Use this for reference geometry — a ghost outline of a component you’re designing something to attach to — that helps you position things but shouldn’t be in the final print.

! (bang / isolate) — renders only this shape, ignoring everything else in the entire file. Use this when you want to check a single module or shape by itself, without every other object in the scene blocking the view.

* (star / disable) — completely disables this shape; it’s not rendered at all and produces no output. Use this to temporarily turn off part of your design during debugging, without deleting the code.

// USING MODIFIERS FOR DEBUGGING:

difference() {
  cube([30, 30, 20]);

  // # highlights the cutting shape so you can see where it's cutting
  # translate([15, 15, -0.001])
    cylinder(h=20.002, r=8, $fn=32);
}

// % ghost reference — helps position but doesn't print
% translate([0, 0, 20])
  cube([30, 30, 5]);   // ghost of a lid that will sit on top

Important

F5 vs F6: F5 runs a fast approximate preview that is NOT manifold-safe — good for quick visual checks only. F6 runs the full CGAL geometric kernel: slower, but accurate and manifold-safe. Always use F6 (or 3dm build) before sending anything to print.


Step 6 — linear_extrude() and rotate_extrude()

Two Ways to Create 3D Shapes from 2D Profiles

You’ve already used linear_extrude() with polygon(). Now let’s understand it more fully, and introduce its sibling rotate_extrude().

linear_extrude(height=N) takes a 2D profile (any 2D shape: circle, square, polygon, or a combination) and pushes it straight up along the Z axis, creating a prism. The cross-section of the prism matches the 2D profile exactly.

Two important optional parameters:

  • twist=angle — rotates the profile as it extrudes, creating a spiral or helix. A twist=90 on a square profile creates a twisted square column.
  • scale=factor — changes the size of the profile from bottom to top. scale=0.5 means the top is half the size of the bottom, creating a tapered shape.

rotate_extrude(angle=360) takes a 2D profile and rotates it around the Z axis, sweeping it in a circle to create a rotationally symmetric solid. Imagine a lathe: the profile is the outline of a piece, and the lathe spins it to create a solid of revolution.

The profile for rotate_extrude() must be positioned in positive X space — to the right of the Z axis. The X distance from the Z axis becomes the radius of the resulting shape. If you place a small circle at X=15 and rotate-extrude it, you get a torus (donut) with a 15 mm ring radius.

// linear_extrude: circle pushed straight up = a cylinder
linear_extrude(height=20) {
  circle(r=10, $fn=32);
}

// linear_extrude with twist: a twisted square column
translate([30, 0, 0])
linear_extrude(height=30, twist=90) {
  square([10, 10], center=true);
}

// linear_extrude with scale: a tapered shape (like a pyramid with a square base)
translate([60, 0, 0])
linear_extrude(height=30, scale=0.1) {
  square([15, 15], center=true);
}

// rotate_extrude: a circle swept around the Z axis = a torus (donut)
translate([0, 50, 0])
rotate_extrude(angle=360, $fn=64) {
  translate([15, 0, 0]) circle(r=5, $fn=32);
}

Any shape that is rotationally symmetric — a bowl, a cup, a ring, a knob, a vase — can and should be made with rotate_extrude(). It’s dramatically more elegant than building the same shape from many overlapping cylinders.


Step 7 — hull() — The Convex Envelope

What hull() Does

hull() computes the convex hull of all its children — the smallest convex shape that completely contains all of them. The easiest mental model: imagine stretching a rubber band around a collection of objects laid on a table. The shape the rubber band makes when it snaps tight around all of them is the convex hull.

Notice the key word: convex. A convex shape has no indentations or concave regions — every surface curves outward. hull() fills in any gaps or concavities between the shapes you give it.

How hull() Differs from union()

union() takes all the shapes and merges them, preserving their individual forms including any gaps or indentations between them.

hull() takes all the shapes and creates the smoothest possible outer envelope that touches or contains all of them, filling in any gaps.

This makes hull() excellent for:

  • Creating smooth transitions between two shapes of different sizes
  • Making rounded boxes (place a small sphere at each corner, take the hull)
  • Creating organic, blob-like shapes
  • Generating ramps and smooth blends
// hull() of three spheres — creates a smooth rounded triangle
hull() {
  translate([0,  0,  0]) sphere(r=5, $fn=32);
  translate([30, 0,  0]) sphere(r=5, $fn=32);
  translate([15, 20, 0]) sphere(r=5, $fn=32);
}

// Practical use: a rounded box
// Place small spheres at the eight corners of a box
// The hull creates a box with perfectly rounded edges
translate([0, 40, 0])
hull() {
  for (x = [3, 27], y = [3, 17], z = [3, 7]) {
    translate([x, y, z]) sphere(r=3, $fn=16);
  }
}

The rounded box pattern is one of the most commonly used techniques in OpenSCAD. The sphere radius controls how round the edges are. The positions of the spheres control the overall box dimensions. Change the sphere radius to change how much rounding you get.


Advanced CSG: Putting It All Together

A Parametric Mounting Bracket

Here is a complete practical example that uses nested CSG operations to create a real functional part. Read through it carefully — notice how the design intent is encoded as named variables at the top, and the geometry simply uses those variables.

// Parametric Mounting Bracket
// Change these values to resize the bracket
width  = 40;    // mm — total bracket width
height = 30;    // mm — total bracket height
depth  = 8;     // mm — bracket thickness (front to back)
hole_r = 4;     // mm — radius of mounting holes
slot_w = 6;     // mm — width of top slot
slot_h = 15;    // mm — height of top slot
wall   = 3;     // mm — material remaining above slot

module bracket() {
  difference() {
    // Base: a solid rectangular block — this is what everything gets cut from
    cube([width, depth, height]);

    // Two circular mounting holes drilled through the Y axis
    // The rotate([-90,0,0]) turns the cylinder to point in the Y direction
    translate([10, -0.001, 10])
      rotate([-90, 0, 0]) cylinder(r=hole_r, h=depth + 0.002, $fn=32);
    translate([30, -0.001, 10])
      rotate([-90, 0, 0]) cylinder(r=hole_r, h=depth + 0.002, $fn=32);

    // A slot cut through the top portion of the bracket
    translate([width/2 - slot_w/2, -0.001, height - slot_h - wall])
      cube([slot_w, depth + 0.002, slot_h]);
  }
}

bracket();

Walk through this mentally: start with a solid block. Drill two circular holes through it from front to back. Cut a slot down from the top. The result is a bracket with two mounting holes and an adjustment slot — all from one parametric design.

Try changing hole_r, slot_w, or width and rebuilding. Watch how every feature adapts automatically.


Quiz — Lesson 2 (15 questions)

  1. What are the four main 3D primitives in OpenSCAD?
  2. What does difference() do? Which child is the base, and which children are the cutting tools?
  3. Why do you add 0.001 mm to the cutting geometry in a difference() operation? What problem does it prevent?
  4. What does the # modifier character do, and when would you use it during debugging?
  5. What is the difference between F5 and F6 in the OpenSCAD GUI? Which should you use before printing?
  6. What does hull() produce? How is it different from union()?
  7. What does the % modifier do to a shape in OpenSCAD?
  8. Describe what rotate_extrude() does and give one example of a shape it could produce.
  9. What does intersection() return when applied to a cube and a sphere that partially overlap?
  10. True or False: the * modifier renders a shape as a transparent ghost for debugging purposes.
  11. Describe what linear_extrude() does and explain what the twist parameter changes.
  12. What is a co-planar face, and what problem does it cause in a difference() operation?
  13. If you want to subtract a cylinder from a cube and the cylinder is exactly as tall as the cube, what two adjustments do you need to make to ensure a clean cut?
  14. When using polygon(), what order should points be listed in, and why?
  15. What is the difference between combining two overlapping shapes with union() versus rendering two separate overlapping objects without any CSG operation?

Extension Problems (15)

  1. Build a hollow sphere with 1.5 mm walls using difference() and the 0.001 mm rule. Document the outer and inner radii you chose and verify the wall thickness using 3dm info.
  2. Create a vase shape using rotate_extrude() and a custom 2D profile. The vase should be wider in the middle than at the top and bottom.
  3. Design a bracket or clip using nested difference() and union(). Add a comment to every CSG step explaining what it does.
  4. Use hull() to create a smooth, rounded box with 3 mm radius corners. Document the sphere placement strategy you used.
  5. Use the % modifier to create a ghost reference shape that helps you position a snap-fit clip around a cylinder. Screenshot the debugging view and explain it.
  6. Create a parametric name badge: a flat rectangular base with your name text embossed (raised) on the top face, using linear_extrude() combined with text(). Make the text height a parameter.
  7. Build a compound hinge using two cylinders (the barrel), a hull() for the hinge leaf, and alignment holes through the barrel. Document the design intent.
  8. Design a 10-sided (decagonal) prism using cylinder() with $fn=10 and a difference() to cut a hexagonal through-hole aligned with the prism’s center.
  9. Create a single test print that exercises all three CSG operations (union, difference, intersection) in one part. Add header comments explaining what each operation does in the design.
  10. Using only cube(), sphere(), difference(), and hull(), build a simple chess pawn. It should be recognizable as a pawn when printed.
  11. Create a lattice cube: a solid cube with a grid of cylindrical holes drilled through it in all three axes. Calculate and document the relationship between hole spacing and remaining wall thickness.
  12. Build a parametric ring using rotate_extrude() where the cross-section shape (round, square, or custom polygon) is easily changeable by modifying a variable.
  13. Research and document the surface() primitive: what input does it accept, what shape does it produce, and when would you use it instead of polyhedron()? Include a working example.
  14. Design a tolerance test set: five pairs of pegs and holes with clearances from 0.0 mm to 0.4 mm in 0.1 mm increments. Print one set and document which clearance allows free movement on your specific printer.
  15. Write a short guide explaining all four modifier characters (#, !, %, *) with one concrete use case for each, and a note on why you must always remove them before exporting the final file.

References and Helpful Resources

  • OpenSCAD User Manual — Primitive Solids and Boolean Operations — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids

  • OpenSCAD User Manual — CSG Modelling — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/CSG_Modelling

  • OpenSCAD User Manual — Transformations and Extrusions — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_the_2D_Subsystem

  • OpenSCAD User Manual — Modifier Characters — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Modifier_Characters

Supplemental Resources

  • Programming with OpenSCAD EPUB Textbook — assets/Programming_with_OpenSCAD.epub — Chapters on CSG and primitives
  • CodeSolutions Repository — https://github.com/ProgrammingWithOpenSCAD/CodeSolutions — Worked examples for CSG, hull, and extrusions
  • OpenSCAD Quick Reference — https://programmingwithopenscad.github.io/quick-reference.html — All primitive and CSG syntax at a glance
  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake — Build workflow reference
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Extension Projects and Reference Appendices

All supporting documents for Lesson 2 are included below. You do not need to open any additional files.


Appendix A: OpenSCAD Quick Reference — Cheat Sheet

Keep this handy during all OpenSCAD work. For full documentation: https://openscad.org/documentation.html


Basic Shapes (Primitives)

cube([length, width, height]);           // rectangular box at origin
cube([l, w, h], center=true);           // box centered at origin

sphere(r=radius);                        // sphere by radius
sphere(d=diameter);                      // sphere by diameter

cylinder(h=height, r=radius);            // cylinder
cylinder(h=height, d=diameter);          // by diameter
cylinder(h=height, r1=5, r2=2);         // cone (different top/bottom radii)

$fn = 50;  // curve resolution — higher = smoother, slower to render

Transformations

translate([x, y, z]) shape;             // move
rotate([x_deg, y_deg, z_deg]) shape;    // rotate around each axis
scale([x, y, z]) shape;                 // scale (1.5 = 150%)
mirror([1, 0, 0]) shape;               // mirror across YZ plane
                                        // use [0,1,0] for XZ, [0,0,1] for XY

Boolean Operations

union() { shape1; shape2; }             // combine shapes
difference() { base; subtract; }        // remove one shape from another
intersection() { shape1; shape2; }      // keep only the overlapping region

Critical rule for difference(): always make the subtracting shape extend 0.001 mm past each shared face to avoid co-planar artifacts.

// Example — box with a through-hole:
difference() {
  cube([30, 30, 10]);
  translate([15, 15, -0.001])           // extends past bottom face
    cylinder(h=10.002, r=5, $fn=32);   // extends past top face
}

Variables and Parameters

length = 70;      // define a variable
width  = 16;
height = 5;

cube([length, width, height]);          // use variables
cube([length * 2, width, height]);      // math in expressions

Modules (Reusable Functions)

// Define:
module my_box(l=20, w=15, h=10) {
  cube([l, w, h]);
}

// Call:
my_box();               // uses all defaults
my_box(30, 20, 8);     // positional arguments
my_box(l=50);           // named argument; others use defaults

Loops

// Repeat a shape N times:
for (i = [0:4]) {                       // i goes 0, 1, 2, 3, 4
  translate([i * 20, 0, 0]) cube([15, 15, 5]);
}

// With step size:
for (i = [0:5:20]) {                    // i goes 0, 5, 10, 15, 20
  translate([i, 0, 0]) sphere(r=3);
}

2D Shapes (for Extrusion)

circle(r=10);                           // 2D circle
square([w, h]);                         // 2D rectangle
polygon([[0,0],[10,0],[5,10]]);         // arbitrary 2D shape

// Extrude into 3D:
linear_extrude(height=5) circle(r=10); // cylinder from 2D circle
linear_extrude(height=10, twist=90)    // twisted extrusion
  square([10, 5]);
rotate_extrude()                        // solid of revolution
  translate([15, 0]) circle(r=3);      // torus

Modifier Characters (Debugging — Remove Before Final Export)

ModifierEffectWhen to use
#Highlight shape in red/orangeFinding where a hole or subtractive shape is
%Render shape as transparent ghostChecking alignment of mating parts
!Render ONLY this shapeIsolating one component for inspection
*Disable (ignore) this shapeTemporarily removing geometry

Warning

Always remove all modifier characters (#, %, !, *) before exporting your final STL. Leaving them in can alter or omit geometry in the exported file.


Useful Functions

len([a, b, c])     // returns 3 — length of a vector
sqrt(25)           // returns 5
pow(2, 8)          // returns 256 (2^8)
abs(-5)            // returns 5
min(3, 5, 1)       // returns 1
max(3, 5, 1)       // returns 5

Keyboard Shortcuts

KeyAction
F5Preview — fast, approximate (use for checking while designing)
F6Full render — exact, required before export
Ctrl + SSave
Ctrl + ZUndo
F3Reset camera view

Export Workflow

  1. Press F6 (full render — wait for it to complete)
  2. File → Export → Export as STL
  3. Save with a descriptive filename: projectname_v2.stl
  4. Run 3dm info on the exported file to verify dimensions before slicing

Appendix B: Bonus Print — Extension Project

Estimated time: 3–5 hours

Overview

This extension project builds on your first successful print by introducing purposeful modification. You’ll take an existing model from an online repository, decide on a specific change that improves or adapts it for a new purpose, apply that change in OpenSCAD or the slicer, and document the entire process. The goal is to experience the design iteration cycle — make a change, understand why you made it, evaluate the result.

Learning Objectives

By completing this project, you will:

  • Apply scaling and simple modifications to an existing model
  • Understand how scaling affects tolerances and assembly fit
  • Document design changes with enough detail that someone else could reproduce your work
  • Practice logging print time, filament use, and outcome for reproducibility

Materials

  • Online repository access (Thingiverse, Printables), slicer, printer, filament

Tasks

  1. Choose a model from Thingiverse or Printables. Note its original stated dimensions.

  2. Decide on a purposeful modification — scale it up or down, add a mounting hole, strengthen a thin feature, or combine it with another model. Write one paragraph explaining what the modification is and why you’re making it. Who benefits from this change?

  3. Apply the change in OpenSCAD (preferred) or by scaling in the slicer. Record the new dimensions and what changed relative to the original.

  4. Slice and print all parts in one session where possible. Log: print time, filament used (in grams), layer height, infill %, and any slicer settings you adjusted.

  5. Create a short construction note: describe how the modified print is used or assembled. Photograph the result.

Probing Questions

  1. What motivated the modification, and who benefits from it?
  2. How did scaling affect tolerances or assembly fit? If the model connects to anything else, did the fit change?

Starter Code

If adapting a model using OpenSCAD, use this scaling scaffold as a starting point:

// Bonus Print Modification Scaffold
// Import an STL and apply modifications parametrically.

// ---- Parameters ----
scale_factor  = 1.5;    // 1.0 = original, 1.5 = 50% larger, 0.75 = 25% smaller
add_mount     = true;   // set false to skip the mount hole
mount_r       = 2.5;    // mm — mount hole radius (for M5 screw: 2.75mm)
mount_pos     = [25, 0, 0]; // mm — position of mount hole center

// ---- Base Model ----
// Replace "original.stl" with your actual file path
module base_model() {
  scale([scale_factor, scale_factor, scale_factor])
    import("original.stl", convexity=10);
}

// ---- Mount Hole (optional) ----
module mount_hole() {
  if (add_mount) {
    translate(mount_pos)
      cylinder(h=100, r=mount_r, center=true, $fn=32);
  }
}

// ---- Assembly ----
difference() {
  base_model();
  mount_hole();
}

Appendix C: Bonus Print — Student Documentation Template

Author: ________________ Date: __________ Description: Modify an existing 3D model and document the design changes and print outcomes.


Original Model

  • Model name and source:
  • Link or file name:
  • Original stated dimensions:
  • Why did you choose this model for modification?

Modification Plan

  • What change will you make, and why?
  • Who benefits from this modification?
  • Will this be done in OpenSCAD, or by scaling in the slicer? Why?

Variant Specifications

VariantScale or ChangeEst. print timeEst. filament (g)Key dimensions
Original (reference)
V1 (your modification)
V2 (optional)

VariantActual print timeActual filament (g)QualityNotes
V1
V2 (if made)

How Does Scaling Affect Fit?

If your model connects to anything (a wall mount, another printed part, a standard fastener), describe how the scaled dimensions affect the fit:

Original mating dimension: ____ mm → Scaled dimension: ____ mm → Fit result:


Reflections

  • Which variant is most effective for its intended purpose, and why?
  • How did scaling or modification affect print time and material use?
  • What trade-offs did you observe (strength vs. speed, size vs. material cost)?
  • If you made a third variant, what would it be?

Attachments Checklist

  • .scad file with modification code (or slicer project file if scaled in slicer)
  • Photos of original and modified prints side by side (if both available)
  • Print log for each variant
  • Completed variant specification table above

Teacher Feedback

CategoryScore (0–3)Notes
Problem & Solution — modification is purposeful; print(s) successful
Design & Code Quality — modification is documented; parametric if done in OpenSCAD
Documentation — variant table complete; scaling effects addressed
Total (0–9)

Appendix D: Real-Life Problem Solver — Extension Project

Estimated time: 4–8 hours (design, adapt, print, and document)

Overview

This extension project asks you to do something harder than downloading and printing: identify a real problem in your life or environment, find or design a 3D-printed solution, adapt it to meet the actual constraints of that situation, and document the full process. This is the closest this course gets to professional design work at this stage — it requires a problem statement, candidate research, a design decision, iteration, and evaluation.

Learning Objectives

By completing this project, you will:

  • Identify a user problem and write a problem statement that defines what success looks like
  • Evaluate candidate printed solutions and choose one to adapt
  • Make at least one documented design modification
  • Test and measure a prototype with documented results
  • Write a final report summarizing performance and next steps

Materials

  • Computer with slicer and access to repositories
  • Printer, filament, basic hand tools for post-processing

Tasks

  1. Write a problem statement. Interview a potential user (yourself counts) and write one paragraph that describes: what the person is trying to do, what gets in their way, and what a successful solution would let them do. Be specific — “it’s inconvenient” is not a problem statement; “my headphones fall off the desk and the cable gets tangled” is.

  2. Research candidate models. Search Thingiverse or Printables for at least three options that could address your problem. List all three in your documentation, explain why each could or couldn’t work, and justify your final selection.

  3. Adapt the model. Make at least one modification — scale it, add or remove features, combine it with another model, or change the material or infill for durability. Document your changes in a short changelog with one entry per change.

  4. Print and test. Run a supervised test of the prototype. Log any failures and what corrective actions you took. If the first print fails or doesn’t work as intended, print again with documented changes.

  5. Write a final report summarizing: how well the prototype performed, measured deviations from specifications, any remaining limitations, and what you would change in the next iteration.

Probing Questions

  1. What assumptions did you make about the user’s context? How could you validate those assumptions with someone other than yourself?
  2. Which modification had the biggest impact on whether the part worked, and why?

Appendix E: Real-Life Problem Solver — Student Documentation Template

Author: ________________ Date: __________ Description: Adapt an existing 3D model to solve a real problem, with documented design changes and test results.


Problem Statement

Write one paragraph. Who is the user? What are they trying to do? What gets in their way? What would a successful solution let them do?


Candidate Models

#Model name and sourceWhy it could workWhy it might not work
1
2
3

Selected model: _____ Reason for selection:


Modification Changelog

#Change madeWhyResult
1
2
3

Original vs. Adapted Specifications

ParameterOriginalAdaptedReason

Design Iteration Cycle

  • Date:
  • Settings (layer height, infill, supports):
  • Result:
  • Issues observed:
  • Next action:
  • Date:
  • What changed from Print 1:
  • Result:
  • Issues resolved / remaining:

Test Results

How did you test whether the prototype solves the problem? What did you observe?

  • Test method:
  • Did the prototype succeed? Yes / Partially / No
  • Any deformation, failure, or fit issues?
  • User feedback (if you had a second person try it):

Reflections

What worked:

What didn’t work:

What you would change in iteration 3:

What this taught you about the gap between a design on screen and a physical object that works in real life:


Accessibility Considerations

  • How would you describe this modified design to someone who cannot see it?
  • What measurements or tactile features would help a non-visual user understand or use the part?

Attachments Checklist

  • Problem statement (one paragraph, specific)
  • Three candidate models with analysis
  • Modification changelog
  • .scad or .stl files for each iteration
  • Photos of each printed iteration
  • Test results documentation
  • Final report (performance summary and next steps)

Teacher Feedback

CategoryScore (0–3)Notes
Problem & Solution — modification functional; problem addressed
Design & Code Quality — changes documented; iteration evident
Documentation — changelog complete; test results recorded; reflection specific
Total (0–9)

Resubmission: attach a paragraph explaining what was changed and why. Resubmission score replaces original.


Appendix F: Real-Life Problem Solver — Instructor Reference

Project Context

This is the most demanding extension project in Lessons 1–2. It requires students to work through a full design loop: problem definition → research → selection → modification → testing → evaluation. The quality of the outcome depends heavily on the quality of the problem statement — students who write a vague problem statement produce vague designs. Front-load the problem statement review.

Key Learning Points to Reinforce

A problem statement is not a solution. Students tend to jump to “I want to print a phone stand” without explaining why. The problem statement should describe a situation and a gap, not a predetermined output. “My phone falls off my desk and I can’t see notifications while working” is a problem statement. “I want a phone stand” is a solution.

A changelog creates accountability. Every design change should have a reason. Students who change things without documenting why have no basis for evaluating whether the change helped. Reinforce this by asking “why did you make this change?” at every iteration review.

Testing must be observable. A test that consists of “I tried it and it worked” is not documentation. Students should describe the test method (how many times, under what conditions, measured how), not just the result.

Constraints (Enforce These)

  • Problem statement must be written before model selection
  • At least one print iteration is required — first-attempt submissions are not acceptable
  • Changelog must have at least one entry per design change
  • Test results must include an observable measurement or observation, not just a pass/fail judgment

Assessment Notes

Strong submissions show: a specific problem statement that identifies a real user, a justified model selection (not just “I found this one”), a changelog that explains the reasoning behind each change, and a test result that describes what was actually measured or observed.

Common weak areas: problem statements that are really solution statements, modification changelogs with a single vague entry, and test sections that say “it worked fine” without any specifics. Push back on all three in feedback.

Extension for advanced students: have them repeat the design loop with a second user who is different from themselves. Designing for yourself and discovering that a different person has different constraints is a powerful experience. -e


Lesson 3 — Parametric Architecture and Modular Libraries

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

You can now create shapes and combine them using CSG. That’s the vocabulary. Now it’s time to learn the grammar — how to organize and generalize your code so it’s maintainable, reusable, and professional.

The difference between a beginner OpenSCAD file and a professional one isn’t usually the shapes — it’s the structure. A beginner file has magic numbers scattered throughout, the same geometry copy-pasted in three places, and no indication of what any variable is for. A professional file has clearly named parameters at the top, organized modules, validation that catches errors before they become bad prints, and code you could hand to someone else and they’d immediately understand.

This lesson introduces the complete system for professional OpenSCAD structure: modules, functions, libraries, and the DRY principle. It also covers one of the most confusing aspects of OpenSCAD for programmers coming from other languages: how variables work here is completely different from Python, JavaScript, or Java — and understanding that difference upfront will save you hours of debugging.


Learning Objectives

By the end of this lesson you will be able to:

  • Understand and work with OpenSCAD’s unique “last-wins” variable scoping rules
  • Write parametric modules with validated inputs using assert()
  • Organize reusable geometry into library files using use and include
  • Write recursive functions for mathematical and spatial computations
  • Apply list comprehensions and vector operations for advanced parametric design
  • Apply the DRY (Don’t Repeat Yourself) principle through modules and functions
  • Use for loops, conditionals, and list comprehensions to generate repetitive geometry
  • Write type-safe modules using is_number(), is_list(), and is_string()

Concept 1: How Variables Work in OpenSCAD (It’s Different)

The Most Important Thing to Understand in This Lesson

If you’ve ever programmed in Python, JavaScript, Java, or almost any other language, you have a mental model of variables that works a certain way: you assign a value, the program runs, and that variable holds that value until you change it. Variables are like buckets — you put a value in, you can read what’s in there, and you can put a new value in later.

OpenSCAD does not work this way. The difference is fundamental and will cause bugs if you misunderstand it. Let’s dig in.

How OpenSCAD Actually Works

OpenSCAD processes your file in two distinct passes:

Pass 1 — Parse: OpenSCAD reads the entire file from top to bottom, collects every variable assignment and module/function definition, and resolves what every variable equals. No geometry is created during this pass.

Pass 2 — Render: OpenSCAD creates geometry using the values that were determined in Pass 1.

This two-pass system leads to three rules that govern all OpenSCAD code:

Rule 1: There is no assignment during execution. You cannot update a variable while the geometry is being computed. Variables are set during parse time and then read during render time. “Updating” a variable mid-computation isn’t a concept in OpenSCAD.

Rule 2: The last assignment in a scope wins — everywhere in that scope. This is the most confusing rule. If you write x = 5; on line 3 and then x = 10; on line 20, the value of x is 10 everywhere in that scope — including on line 3, even though you hadn’t written the second assignment yet. It’s as if OpenSCAD reads the entire file first, decides what everything equals, and then uses those final values. Writing x = 5; echo(x); x = 10; will print 10, not 5.

Rule 3: Variables inside modules are local. A variable declared inside a module exists only within that module. The global variable with the same name is unchanged.

// COMMON MISTAKE — expecting x to change during execution
x = 5;
echo("x =", x);   // This prints 10, NOT 5 — because the last assignment wins
x = 10;

// CORRECT PATTERN — each value gets its own name
base_size    = 20;          // 20
padded_size  = base_size + 10;   // 30 — computed from base_size
doubled_size = base_size * 2;    // 40 — computed from base_size
echo(base_size, padded_size, doubled_size);  // 20, 30, 40

// MODULE SCOPE — variables inside a module are completely separate
wall_t = 3;   // global wall thickness

module demo_box(size) {
  wall_t = 1;           // This is a DIFFERENT variable — local to this module
  cube([size, size, wall_t]);   // uses the local wall_t = 1
}

demo_box(20);
echo("Global wall_t is still:", wall_t);  // Still 3 — unchanged by the module

// CHOOSING BETWEEN VALUES conditionally — use a ternary expression
mode = "large";
box_size = (mode == "large") ? 40 : 20;   // If mode is "large", 40; otherwise 20
cube([box_size, box_size, 5]);

What This Means in Practice

Because you can’t update a variable during execution, you can’t accumulate a total like total = total + item. Instead, you describe relationships between values mathematically. If the width of your inner wall depends on the outer wall and the wall thickness, you write that as a formula: inner_width = outer_width - 2 * wall_t;. The system computes the value once, and that value is used everywhere.

This is actually quite elegant once you adjust to it. You’re writing equations, not instructions. Each variable is defined once and means exactly one thing.

For cases where you genuinely need to choose between values or compute something iteratively, OpenSCAD provides ternary expressions (condition ? value_if_true : value_if_false), recursive functions, and list comprehensions — all covered in this lesson.


Step 1 — Modules: Named, Reusable Geometry

What a Module Is

A module is a named, reusable piece of geometry. When you find yourself writing the same shape code in multiple places, that’s the signal to create a module. Modules accept parameters — just like functions in other languages — so you can write one module that creates many different variations of the same shape.

The syntax is:

module name(param1, param2=default_value) {
  // geometry code here
  // uses param1 and param2
}

Parameters with default values (param2=default_value) are optional — callers can omit them and the default will be used. Parameters without defaults are required.

You call a module just like a statement:

name(value1, value2);

The DRY Principle

Tip

DRY — Don’t Repeat Yourself. If geometry is defined in one module, changing it once updates everywhere it’s used. Copy-pasting the same geometry multiple times means one missed update creates inconsistency across your design.

If you need four mounting holes in a plate, you could write the cylinder code four times — once for each hole. But now if you need to change the hole size, you have to change it in four places. If you miss one, your design is inconsistent. If you need to add a fifth hole later, you have to remember the pattern and paste it again.

The DRY approach: write a module mounting_hole(r, depth) once, then call it four times. Now the hole geometry is defined in exactly one place. Change it once, every hole updates. Add more holes as easily as one line each.

// WRONG — copy-pasted, hard to maintain
difference() {
  cube([60, 40, 5]);
  translate([5,  5,  -0.001]) cylinder(r=2, h=5.002, $fn=16);
  translate([55, 5,  -0.001]) cylinder(r=2, h=5.002, $fn=16);
  translate([5,  35, -0.001]) cylinder(r=2, h=5.002, $fn=16);
  translate([55, 35, -0.001]) cylinder(r=2, h=5.002, $fn=16);
}

// CORRECT — DRY: one module, used multiple times
module mounting_hole(r=2, depth=5) {
  // The 0.001 offsets prevent co-planar face problems (Lesson 2)
  translate([0, 0, -0.001])
    cylinder(r=r, h=depth + 0.002, $fn=16);
}

difference() {
  cube([60, 40, 5]);
  translate([5,  5,  0]) mounting_hole();
  translate([55, 5,  0]) mounting_hole();
  translate([5,  35, 0]) mounting_hole();
  translate([55, 35, 0]) mounting_hole();
}

The second version is easier to read, easier to change, and scales effortlessly. If you need a larger hole, change r=2 to r=3 in one place, and all four holes update.


Step 2 — assert() for Parameter Validation

Why Your Modules Should Validate Their Inputs

In a parametric design, other people (and future-you) will change parameter values. What happens if someone sets wall_thickness = 0? Or cylinder_radius = -5? Depending on the code, it might silently produce garbage geometry, or it might produce a cryptic error that doesn’t explain what went wrong.

assert() is OpenSCAD’s built-in validation statement. It takes a condition and an optional message. If the condition is false, OpenSCAD stops rendering immediately and displays your message in the console. This is vastly better than allowing invalid values to silently produce a broken model.

Think of assert() as making your design constraints machine-enforceable. Instead of just knowing that wall_t must be at least 1.2 mm for a 0.4 mm nozzle, you write it as an assertion and the tool enforces it automatically.

How assert() Works

assert(condition, "message if condition is false");

If condition evaluates to true, nothing happens — the code continues normally. If condition is false, the render stops and the message is printed. The message should be descriptive enough that anyone reading it immediately understands what went wrong.

module safe_cylinder(r, h, fn=32) {
  // Validate all inputs before creating any geometry
  assert(is_num(r) && r > 0,
    str("safe_cylinder: radius must be a positive number, got: ", r));
  assert(is_num(h) && h > 0,
    str("safe_cylinder: height must be a positive number, got: ", h));
  assert(fn >= 3,
    str("safe_cylinder: fn must be at least 3, got: ", fn));
  assert(r < 500,
    str("safe_cylinder: radius ", r, "mm seems wrong — did you enter cm instead of mm?"));

  cylinder(r=r, h=h, $fn=fn);
}

safe_cylinder(5, 20);          // fine
// safe_cylinder(-3, 20);      // STOPS: "radius must be a positive number, got: -3"
// safe_cylinder(5, 20, fn=1); // STOPS: "fn must be at least 3, got: 1"

The str() function assembles a string from multiple values — very useful for error messages that include the bad value so the user knows exactly what to fix.

Tip

Add assert() statements to every module at the very top of the module body, before any geometry. This turns bad-input problems into clear, descriptive messages instead of mysterious rendering failures.


Step 3 — Library Files: use vs. include

Organizing Code Across Multiple Files

Once you have a collection of useful modules — mounting holes, standoffs, snap clips, text labels — you’ll want to reuse them across multiple projects without copy-pasting them every time. The solution is a library file: a separate .scad file containing only module and function definitions, which you can import into any project.

There are two ways to load a library:

use <filename.scad> — imports only the module and function definitions from the file. Any top-level geometry statements in the file (bare cube(), cylinder(), etc.) are not executed. This is almost always what you want: you want the tools, not any leftover test geometry the library file might contain.

include <filename.scad> — executes the entire file, including any top-level geometry statements. If the library file has a cube([10,10,10]); at the top level, that cube will appear in your model. Use this sparingly and intentionally.

Note

use <file.scad> imports only module/function definitions — top-level geometry in the file is ignored. include <file.scad> executes the entire file including any top-level geometry. Prefer use for libraries to avoid unexpected geometry.

// === lib/hardware.scad ===
// A reusable hardware library. Load with: use <../lib/hardware.scad>

module m3_bolt_hole(depth=10, countersink=false) {
  // M3 clearance hole: 3.4mm diameter (ISO standard M3 clearance)
  assert(depth > 0, "m3_bolt_hole: depth must be positive");
  translate([0, 0, -0.001]) {
    cylinder(d=3.4, h=depth + 0.002, $fn=16);
    if (countersink) {
      // Add a countersunk cone for flat-head screws
      translate([0, 0, depth - 2.5])
        cylinder(d1=3.4, d2=7.0, h=3, $fn=32);
    }
  }
}

module m3_standoff(height=5, outer_d=6) {
  // Hollow cylindrical standoff with M3 hole through center
  assert(height > 2, "m3_standoff: height must be > 2mm");
  difference() {
    cylinder(d=outer_d, h=height, $fn=16);
    m3_bolt_hole(depth=height);  // Modules can call other modules from the library
  }
}
// === src/main.scad ===
use <../lib/hardware.scad>   // loads definitions; no top-level geometry executes

// Place M3 standoffs at all four corners of a mounting plate
cube([60, 40, 5]);
for (pos = [[5,5], [55,5], [5,35], [55,35]]) {
  translate([pos[0], pos[1], 0])
    m3_standoff(height=8);
}

Structuring a Good Library

A well-organized library groups related modules, documents each one, and validates inputs. Here’s a template:

// ============================================================
// fasteners.scad — Parametric fastener library
// Usage: use <fasteners.scad>
// All dimensions follow ISO metric standards.
// ============================================================

module m3_hole(depth=10) {
  // M3 clearance hole: 3.2mm diameter
  cylinder(r=1.6, h=depth + 0.001, $fn=16);
}

module m4_hole(depth=10) {
  // M4 clearance hole: 4.3mm diameter
  cylinder(r=2.15, h=depth + 0.001, $fn=16);
}

module m3_nut_trap(extra_depth=0) {
  // M3 hex nut trap: 6.4mm across-flats, 2.4mm thick
  cylinder(r=3.2, h=2.4 + extra_depth, $fn=6);  // $fn=6 makes a hexagon
}

Step 4 — for Loops and Conditionals

Repeating Geometry with for

OpenSCAD’s for loop iterates over a list or range and creates geometry for each iteration. Each iteration is independent — you can’t pass values between iterations. But you can create geometry in each one.

Three forms:

for (variable = list) — iterates over every element in a list.

for (variable = [start : end]) — iterates over a range with a step of 1. [0:5] gives 0, 1, 2, 3, 4, 5.

for (variable = [start : step : end]) — iterates over a range with a specified step. [0:45:315] gives 0, 45, 90, 135, 180, 225, 270, 315.

// Place pegs at four specific positions
peg_positions = [[0,0], [20,0], [40,0], [20,20]];

for (pos = peg_positions) {
  translate([pos[0], pos[1], 0]) cylinder(r=3, h=10, $fn=32);
}

// Place cylinders every 45° around a circle (8 cylinders total)
for (angle = [0 : 45 : 315]) {
  rotate([0, 0, angle])
    translate([20, 0, 0])
      cylinder(r=2, h=5, $fn=16);
}

// Conditional: if show_lid is true, draw a lid
show_lid = true;
if (show_lid) {
  translate([0, 0, 30]) cube([50, 30, 3]);
}

Evenly spacing around a circle: If you want N objects evenly spaced, the angular step is 360 / N. For 12 objects, that’s 30° each. Use [0 : 360/N : 360 - 360/N] to avoid duplicating the first position at 360°.

Using for with Multiple Variables

You can use multiple for clauses in a single statement to create grids:

// 4×4 grid of cylinders — nested for in a single statement
for (x = [0:3], y = [0:3]) {
  translate([x * 20, y * 20, 0]) cylinder(r=3, h=5, $fn=16);
}

This is equivalent to two nested for loops but more compact.


Step 5 — Recursive Functions

Why OpenSCAD Needs Recursion

Most programming languages let you write a loop that accumulates a value: total = 0; for item in list: total += item. OpenSCAD doesn’t allow this — variables are fixed after parse time. So when you need to compute something iteratively, you use recursive functions.

A recursive function is one that calls itself with a smaller version of the problem. Every recursive function has two parts:

The base case — the input is simple enough to handle directly, so return an answer without recursing.

The recursive case — reduce the problem slightly and call yourself with the smaller version, then combine the result.

Functions vs. Modules — A Critical Distinction

Before we look at examples, there is an important rule in OpenSCAD that trips up almost every programmer coming from other languages:

Functions return values (numbers, strings, lists). They cannot create geometry.

Modules create geometry. They cannot return values.

Important

This is a hard boundary in OpenSCAD: Functions return values — they cannot create geometry. Modules create geometry — they cannot return values. A function with a cylinder() call inside it won’t work, and a module cannot return a value.

// FUNCTION — computes and returns a value
// This is a function because it's defined with "function" and uses "="
function factorial(n) = (n <= 1) ? 1 : n * factorial(n - 1);

echo(factorial(5));   // prints 120
echo(factorial(0));   // prints 1

// Another function: Fibonacci sequence
function fib(n) = (n <= 1) ? n : fib(n-1) + fib(n-2);

// Use the function to space pegs with Fibonacci spacing
// fib(2)=1, fib(3)=2, fib(4)=3, fib(5)=5, fib(6)=8, fib(7)=13, fib(8)=21, fib(9)=34
for (i = [2:9]) {
  translate([fib(i) * 4, 0, 0])
    cylinder(r=1.5, h=5, $fn=16);
}

// A useful function: generate N evenly-spaced values between start and stop
function linspace(start, stop, n) =
  (n <= 1)
    ? [start]
    : concat([start], linspace(start + (stop - start) / (n - 1), stop, n - 1));

positions = linspace(0, 50, 6);   // evaluates to [0, 10, 20, 30, 40, 50]
echo("Positions:", positions);

for (p = positions) {
  translate([p, 0, 0]) sphere(r=2, $fn=16);
}

Reading a Recursive Function

The factorial function works like this:

  • factorial(5) → is n <= 1? No. → return 5 * factorial(4)
  • factorial(4) → is n <= 1? No. → return 4 * factorial(3)
  • …and so on until…
  • factorial(1) → is n <= 1? Yes. → return 1

Then the chain unwinds: 1 * 2 * 3 * 4 * 5 = 120.

The ternary expression (condition) ? value_if_true : value_if_false is the standard way to write the base-case branch in OpenSCAD functions.


Step 6 — List Comprehensions

What a List Comprehension Is

A list comprehension is a compact way to generate a list by applying an expression to every element of a range or existing list, optionally filtering elements. Instead of writing a loop that builds a list step by step, you describe the entire list in one expression.

The syntax:

[for (variable = range_or_list) expression]
[for (variable = range_or_list) if (condition) expression]

List comprehensions are OpenSCAD’s answer to the fact that you can’t use for loops to accumulate values. If you need a list of computed values, a comprehension gives you the entire list at once.

// Generate heights: [5, 10, 15, 20, 25]
heights = [for (i = [1:5]) i * 5];
echo(heights);   // [5, 10, 15, 20, 25]

// Generate 8 evenly-spaced positions along the X axis
positions = [for (i = [0:7]) [i * 12, 0, 0]];
for (pos = positions) {
  translate(pos)
    cylinder(h = 5 + pos[0] * 0.3, r=3, $fn=16);  // height increases with X position
}

// Filter: generate only even numbers from 0 to 18
evens = [for (i = [0:9]) if (i % 2 == 0) i * 2];
echo(evens);   // [0, 4, 8, 12, 16]

// 2D grid of points — nested comprehension generates a flat list of [x,y,0] vectors
grid = [for (x = [0:3]) for (y = [0:3]) [x * 20, y * 20, 0]];
for (pt = grid) {
  translate(pt) cylinder(r=2, h=8, $fn=16);
}

List comprehensions are the preferred way in OpenSCAD to generate lists of positions, sizes, or other computed values that drive the placement of geometry. Master them and you’ll be able to generate complex repetitive patterns with very compact code.


Step 7 — Vector Math and Math Functions

Working with Vectors

Positions and dimensions in 3D space are naturally expressed as vectors — lists of three numbers representing X, Y, and Z. OpenSCAD supports arithmetic directly on vectors, which makes geometric calculations much more readable.

v1 = [10, 20, 5];
v2 = [3, 4, 0];

sum    = v1 + v2;    // [13, 24, 5]  — add matching components
diff   = v1 - v2;    // [7,  16, 5]  — subtract matching components
scaled = v1 * 2;     // [20, 40, 10] — multiply each component by a scalar
dot    = v1 * v2;    // 110          — dot product: v1·v2 = 10*3 + 20*4 + 5*0
length = norm(v1);   // ≈ 22.9       — Euclidean length (√(10² + 20² + 5²))

Important Math Functions

abs(-5)         // 5    — absolute value
ceil(3.2)       // 4    — round up to nearest integer
floor(3.8)      // 3    — round down to nearest integer
round(3.5)      // 4    — round to nearest integer
max(3, 7, 2)    // 7    — largest of all arguments
min(3, 7, 2)    // 2    — smallest of all arguments
pow(2, 8)       // 256  — 2 raised to the power 8
sqrt(144)       // 12   — square root

>[!IMPORTANT]
>OpenSCAD trigonometry uses **degrees, not radians**. `sin(90)` = 1 (correct). If you pass radians by mistake, your geometry will be wildly wrong.

// Trigonometry — CRITICAL: OpenSCAD uses DEGREES, not radians
sin(90)         // 1    — sine of 90 degrees
cos(0)          // 1    — cosine of 0 degrees
tan(45)         // 1    — tangent of 45 degrees
atan2(1, 1)     // 45   — arctangent of y/x, safe for all quadrants

The atan2(y, x) function deserves special attention. When you need to convert a (x, y) position to an angle, the naive approach atan(y/x) fails when x is zero or negative (wrong quadrant). atan2(y, x) handles all cases correctly by taking both components separately.


Step 8 — Controlling Curve Quality with $fn, $fa, $fs

Why You Need to Think About This

Spheres, cylinders, and circles in OpenSCAD are approximations — they’re actually polygons with many flat faces. The more faces, the smoother the curve looks, but the longer the render takes and the larger the file.

$fn (facets number) — sets the exact number of faces. $fn=8 gives a rough octagon. $fn=64 gives a very smooth circle. Setting it on a single shape overrides the global value for that shape only.

$fa (minimum angle per face) — the smaller this is, the more faces large curves get. Default: 12°.

$fs (minimum face size in mm) — very small features automatically use more faces. Default: 2 mm.

When all three are specified, OpenSCAD uses whichever produces the most faces.

// During development: low $fn for fast rendering
sphere(r=10, $fn=8);     // rough but fast

// For final export: high $fn for smooth curves
translate([30, 0, 0])
  sphere(r=10, $fn=64);  // smooth for printing

// Set globally at the top of a file:
$fa = 5;    // max 5 degrees per face
$fs = 0.5;  // minimum 0.5mm face size (more faces on small features)

Recommended practice: set $fn=16 or $fn=24 during development for fast iteration. Use $fn=64 or higher for spheres and visible curves in the final exported file. Use $fn=32 for functional cylindrical features like bolt holes — it’s smooth enough for function without being slow to render.


Exercises

Exercise 3.1: Write a module safe_box(w, d, h, wall=2) that validates all parameters with assert() and creates a hollow box. Add a constraint that wall must be less than half of the smallest dimension.

Exercise 3.2: Create a library file lib/fasteners.scad with modules for M2, M3, and M4 bolt holes. Use use to load it in a main file and place holes at the four corners of a 60 × 40 mm plate.

Exercise 3.3: Write a recursive function sum_list(lst, i=0) that returns the sum of all elements in a list. Use it to compute the total volume of a set of cylinders.

Exercise 3.4 (Advanced): Use a list comprehension to generate a 5×5 grid of cylinders where each cylinder’s height equals row_index + col_index + 1. Use echo() to verify the maximum and minimum height values.


Quiz — Lesson 3 (15 questions)

  1. What is the DRY principle and why is it important in parametric OpenSCAD design?
  2. What is the difference between a module and a function in OpenSCAD?
  3. What does include <library.scad> do differently from use <library.scad>? When would you use each?
  4. If you write x = 5; on line 3 and x = 10; on line 20 in the same file, what is the value of x everywhere in that file? Why?
  5. What does is_number() return, and give one example of when to use it in a module.
  6. What does the list comprehension [for (i=[0:5:20]) i*2] evaluate to?
  7. What does the echo() function do in OpenSCAD, and where does its output appear?
  8. True or False: a function in OpenSCAD can contain a cylinder() call and create geometry.
  9. How do you specify a default parameter value in an OpenSCAD module? Write an example.
  10. What is the ternary operator in OpenSCAD? Write an example that picks a box size based on a "small" or "large" variable.
  11. Write an OpenSCAD for loop that places 8 cylinders evenly spaced around a circle of radius 25.
  12. What is the difference between [0:10] and [0:2:10] as OpenSCAD range expressions?
  13. Explain why you might use assert() in a module rather than relying on the caller to pass correct values.
  14. Describe how a recursive function works. What are the two required parts of any recursive function?
  15. A library file called shapes.scad contains a module rounded_box(...) and also a top-level cube([5,5,5]);. What happens when you load it with use? What happens when you load it with include?

Extension Problems (15)

  1. Create a bolts.scad library with M3, M4, and M5 clearance holes and nut traps. Use it in a test plate with one of each type.
  2. Build a parametric pegboard using a for loop. Parameters: cols, rows, spacing, peg_r, peg_h. Every parameter should have an assert() validation.
  3. Implement a recursive function that generates a Fibonacci sequence up to n terms and use it to space objects with Fibonacci distances.
  4. Build a module that validates all its inputs using assert() and logs informational output with echo(). Document when assert() halts rendering vs. what echo() does.
  5. Create two library files — one for mechanical fasteners and one for decorative shapes — and use both in one combined project.
  6. Design a parametric gear profile module with teeth, module_size, and thickness parameters. Use assert() to validate that the number of teeth is at least 8.
  7. Build a “shelf peg” system: a board with N parametrically positioned holes and matching pegs sized to press-fit into them.
  8. Use a list comprehension to generate a spiral path of evenly-spaced points and place a small sphere at each point on the spiral.
  9. Extend a fastener library with threaded insert pockets for M3, M4, and M5 heat-set inserts, with the insert dimensions as parameters.
  10. Write a module that draws a text label with a surrounding rectangular border frame. Parameters: text_str, font_size, padding, border_thickness.
  11. Build a parametric snap-fit lid for a rectangular box using for loops to generate evenly-spaced snap clips around the perimeter.
  12. Write a module that takes a list of 3D coordinate vectors as input and draws a connecting chain of cylinders between consecutive points.
  13. Create a parametric honeycomb panel module. Parameters: rows, cols, cell_r, wall_t, depth. Each cell should be a hexagonal through-hole.
  14. Research the BOSL2 library (https://github.com/BelfrySCAD/BOSL2). Find two modules that solve problems you’ve encountered in this course, and write a documented example using each.
  15. Design a comprehensive test suite: build 10 small parametric shapes each specifically testing a different OpenSCAD feature from this lesson. Export them all from one main file that uses a for loop.

References and Helpful Resources

  • OpenSCAD User Manual — Modules — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/User-Defined_Functions_and_Modules

  • OpenSCAD User Manual — For Loops and Conditionals — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#for_loop

  • BOSL2 Library Documentation — https://github.com/BelfrySCAD/BOSL2/wiki

  • OpenSCAD User Manual — Include and Use — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Include_Statement

Supplemental Resources


Lesson 4 — AI-Enhanced Verification and Multimodal Feedback

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

Every lesson so far has ended with “build and verify.” But what does verification actually mean? And when can you trust the result? This lesson is about that question.

The workflow you’ve been using — 3dm build followed by 3dm info — involves two types of tools: deterministic tools (which always give the same answer for the same input) and AI tools (which interpret and describe, but can be vague or wrong). Knowing the difference, and knowing which to use when, is one of the most important skills in modern digital fabrication.

Many beginners treat AI output as authoritative. When 3dm info says “a small peg-like protrusion,” they assume everything is correct. But AI descriptions can be vague, can miss features, and can be flat-out wrong about specifics. This lesson gives you a structured, layered verification approach that combines AI descriptions, deterministic tools, and your own judgment — and makes clear which tool to reach for in which situation.


Learning Objectives

By the end of this lesson you will be able to:

  • Use 3dm info effectively and know its real capabilities and limitations
  • Verify AI-generated OpenSCAD code systematically before printing
  • Build a personal verification chain for any critical design feature
  • Use 3dm preview and slicer layer view as verification methods
  • Apply AI description to accessibility workflows for visually impaired makers
  • Distinguish deterministic from AI-assisted validation
  • Apply prompt engineering techniques for better AI design feedback
  • Recognize when to trust, question, or reject AI suggestions
  • Understand data privacy considerations when using cloud AI tools

Concept 1: Deterministic vs. AI-Based Validation

Two Fundamentally Different Types of Tools

When you run 3dm info after a build, you get two very different types of information in the same output. It’s critical to understand the difference.

Deterministic output comes from directly reading the geometry of the STL file — no interpretation involved. The bounding box (30.0 × 20.0 × 10.0 mm) is computed from the actual vertex coordinates in the mesh. The volume is computed from the triangle faces. These numbers are produced by a formula applied to the file, and they will be identical every time you run the command on the same file. There is no randomness, no ambiguity, no “interpretation.” If the bounding box says 30.0 mm, your model is 30.0 mm wide — full stop.

AI-based output is the natural-language description portion of 3dm info. An AI vision model “looks at” a rendered image of your model and generates a text description. This is fundamentally different: it involves interpretation, and interpretations can vary. The same model might be described as “a small peg” one time and “a narrow cylindrical protrusion” another time. The AI might miss a feature that is too small to be clearly visible. It might describe a 3.2 mm hole as “approximately 3 mm” or “roughly 3–4 mm.” The description is genuinely useful for a quick sanity check, but it is not a measurement.

The Rule That Follows from This

Always verify critical dimensions using deterministic methods first. Bounding box, volume, triangle count — these are computed from the mesh and cannot lie if the build succeeded. Only after confirming the numbers should you look at the AI description, and then only for orientation and general-shape confirmation.


Step 1 — Using 3dm info Effectively

What 3dm info Does

3dm info runs after 3dm build and produces a report about your built STL file. It always includes deterministic data (bounding box, volume, triangle count) and optionally generates an AI description by rendering the model from a specific angle.

# Standard usage — run after every build
3dm build
3dm info

# Request a description from a specific viewing angle
3dm info --view front
3dm info --view top
3dm info --view isometric

# Save the description to a log file
3dm info --output description.txt

# Windows PowerShell
3dm info | Out-File -FilePath description.txt -Encoding UTF8

# Windows CMD
3dm info > description.txt

What 3dm info Does Well

3dm info is genuinely useful for:

Overall shape identification — confirming a part is roughly the right shape. If you designed a bracket and the description says “an L-shaped bracket,” that’s a useful confirmation that the basic geometry is correct.

Relative positions — confirming which part is on top of which, or that a protrusion sticks out from the side rather than the front.

Component counting — “a base plate with four cylindrical protrusions” tells you the four pegs you expected are there and visible.

Accessibility — a student who cannot easily see a rendered 3D model can use 3dm info to get a verbal description of what they’ve built.

What 3dm info Does Poorly

3dm info is not reliable for:

Precise measurements — it cannot replace checking the bounding box or using calipers. “Approximately 10 mm” is not the same as “exactly 9.8 mm.”

Small features — features smaller than about 1–2 mm may not be clearly visible in the rendered view and might be ignored or described vaguely.

Internal geometry — walls, cavities, and internal structures that aren’t visible on the exterior surface won’t be described.

Tolerance-critical features — a 0.2 mm clearance gap that determines whether two parts fit together is invisible to visual AI.


Step 2 — The Verification Escalation Chain

A Layered Approach to Verification

When you need to confirm that your design is correct, don’t jump straight to printing. Instead, follow a layered chain of verification methods from most reliable (and fastest) to most authoritative (and slowest). Start at the top and only go further down if you need more certainty.

Level 1 — Bounding Box and Volume (always accurate)

The very first thing to check after every build. If these numbers don’t match your design intent, something is wrong and you stop here to fix it before going further.

3dm info
# Look for: Bounding Box: [expected width] × [expected depth] × [expected height] mm
# Look for: Volume: [reasonable volume] mm³

Level 2 — Slicer Layer Preview

Open build/main.stl in your slicer (PrusaSlicer, Cura, etc.) and step through layers one at a time. Each layer is a cross-section through your model at a specific height — like slicing a loaf of bread and looking at each slice. This reveals:

  • Wall thicknesses that the bounding box can’t show
  • Internal geometry and cavities
  • Whether holes cut all the way through or stop short
  • Overhanging geometry that may need supports

The slicer layer view is the best non-physical verification tool available. Use it for anything more complex than a simple box.

Level 3 — Isolate and Test a Single Module

If your full model is complex and 3dm info gives a vague or confusing description, temporarily modify your file to render only the specific module you’re trying to verify:

// Temporarily comment out everything else, render only one module
// full_assembly();     // commented out
// base_plate();        // commented out
snap_clip();            // only this renders — easier for 3dm info to describe

Build and run 3dm info on just that isolated piece. A simpler model gives more reliable AI descriptions and easier-to-check bounding boxes.

Level 4 — Physical Measurement

For anything tolerance-critical — a hole size that determines fit, a slot width for a specific component, a snap-fit clearance — print a test coupon and measure with digital calipers. Physical measurement is the ground truth. Nothing replaces it for precise fit verification.

Lesson 8 covers test coupons in detail, but the principle is simple: design a small, fast-printing test piece that includes only the critical feature you’re validating. Print it, measure it, and adjust before printing the full part.


Step 3 — A Verification Log

Creating an Audit Trail

When you verify a design feature, record which method you used and what it confirmed. This creates a professional audit trail — evidence that you thought carefully about whether your design was correct.

Here’s a simple verification log format:

DESIGN VERIFICATION LOG
Project: phone_stand_v2.scad
Date: 2026-03-10

Feature: USB-C charging slot
  Designed: 9.5mm wide × 3.5mm tall
  Level 1 — Bounding box of isolated slot_module(): 9.5 × 3.5mm ✓
  Level 2 — Slicer layer view: rectangular hole visible at Z=5–8.5mm ✓
  Level 3 (AI): "rectangular cutout, approximately 10mm wide" (too vague for precision)
  Level 4 — Calipers after first test print: 9.4mm wide (0.1mm under — acceptable) ✓

Feature: Rubber foot posts (4×)
  Designed: 3.0mm diameter × 2.0mm tall
  Level 1 — Bounding box of isolated foot_post(): 3.0 × 3.0 × 2.0mm ✓
  Level 2 — Slicer: four small protrusions visible on bottom face ✓
  Level 3 (AI): "four small round protrusions" ✓
  Level 4 — Not yet printed

This log takes a few minutes to fill in, and it demonstrates exactly the kind of professional thinking that certification assessments reward.


Step 4 — AI-Generated OpenSCAD Code: How to Verify It

AI Can Write Code, but You Must Check It

AI tools like Claude or ChatGPT can write OpenSCAD code from a plain-English description. This is a genuinely useful way to get a first draft of a design quickly. But AI-generated OpenSCAD code is frequently wrong in subtle ways. The code will look plausible, it may even build without errors, and it can still produce geometry that doesn’t match your intent or that will fail in the slicer.

The most common errors AI makes in OpenSCAD:

Forgetting the 0.001 co-planar rule. The AI writes a difference() with touching surfaces and omits the critical offset. The code looks correct, but the cut may produce rendering artifacts or non-manifold geometry.

Python-style variable reassignment. The AI writes x = 5; x = x + 1; as if variables work like Python, which doesn’t work in OpenSCAD (remember from Lesson 3: last assignment wins at parse time).

Wrong transform order. The AI reverses the order of translate() and rotate(), producing geometry in the wrong location. In OpenSCAD, transforms are applied in reverse order — rotate() then translate() is not the same as translate() then rotate().

Non-manifold geometry. The code looks correct but produces a solid that isn’t a properly sealed, watertight mesh. Slicers will reject it or produce incorrect layers.

Wrong clearance values. The AI invents plausible-sounding tolerances (like “0.1 mm clearance”) that don’t match your specific printer. Tolerances must be calibrated — they can’t be looked up in a general reference.

The AI Code Verification Checklist

Apply these checks to every piece of AI-generated OpenSCAD code before treating it as correct:

AI CODE VERIFICATION CHECKLIST
Run each check in order. Do not proceed if a check fails.

[ ] 1. SYNTAX
      3dm build → does it compile without errors?

[ ] 2. DIMENSIONS
      3dm info → does the bounding box match what you asked for?

[ ] 3. BOOLEAN OPERATIONS
      Does every difference() use the 0.001 offset rule?
      Look for: translate([*, *, 0]) inside difference()
      Should be: translate([*, *, -0.001])

[ ] 4. PARAMETER BEHAVIOR
      Change each parameter to an extreme value (minimum, maximum, zero).
      Does the model change correctly? Are there any edge cases that break it?

[ ] 5. MANIFOLD CHECK
      Open build/main.stl in your slicer.
      Are there any geometry warnings or errors?

[ ] 6. PRINT FEASIBILITY
      Are all walls at least 1.2mm thick for your nozzle size?
      Are there any overhangs steeper than 45°?
      Are all features large enough to be printable?

Step 5 — Prompt Engineering for Better AI Results

Weak Prompts Produce Weak Results

The quality of AI output depends heavily on the quality of your input prompt. A vague request produces a vague or incorrect response. A specific, structured request produces specific, actionable feedback.

Weak prompt:

Review my OpenSCAD code.

This gives the AI almost no information about what to look for. The response will be generic and may miss exactly the issues you care about.

Strong prompt:

I have an OpenSCAD model of a parametric mounting bracket with two M3 bolt holes.
Parameters: width=40, height=30, depth=8, hole_r=3.2.

Please review this code for:
1. Correct use of the 0.001 offset rule in all difference() operations
2. Manifold-safe geometry (no co-planar faces)
3. Whether hole_r=3.2mm is the correct M3 clearance hole diameter per ISO standards
4. Any parameter combinations that could produce invalid geometry

For each issue found, provide:
- Severity: critical / warning / note
- Line number (if applicable)
- Explanation of the problem
- Suggested fix

This prompt tells the AI exactly what to look for, what standard to check against, and how to format its response. The output is dramatically more useful.

Four Characteristics of a Strong Code Review Prompt

Specificity — name the design, state the parameters, describe the intent. Don’t make the AI guess what you’re trying to build.

Explicit criteria — list the specific things you want checked. If you’re worried about the 0.001 rule, say so. If you want to verify dimensional correctness, specify the intended dimensions.

Standard references — mention the standards or rules you want applied (“ISO M3 clearance hole”, “0.001 co-planar offset rule”, “minimum 1.2mm wall for 0.4mm nozzle”).

Output format request — ask for a structured response (severity, line, explanation, fix) rather than a prose paragraph.


Step 6 — Design Intent Guards with assert()

Making Constraints Automatic

In Lesson 3, you learned how to use assert() inside modules to validate parameters. You can also use assert() at the top level of your file to enforce the same constraints you’d put in your verification log. This turns manual checks into automatic ones.

// Top-level design constraints
// These run before any geometry is computed.
width  = 30;
height = 10;
wall_t = 2;

assert(width  >= 10, str("width must be >= 10mm for structural integrity, got: ", width));
assert(height >= 5,  str("height must be >= 5mm to fit standard hardware, got: ", height));
assert(wall_t >= 1.5, str("wall_t must be >= 1.5mm to print reliably with 0.4mm nozzle, got: ", wall_t));
assert(wall_t < width / 2,
  str("wall_t (", wall_t, ") must be less than half of width (", width/2, ")"));

// Geometry — guaranteed to be within valid bounds by the asserts above
difference() {
  cube([width, width, height]);
  translate([wall_t, wall_t, -0.001])
    cube([width - 2*wall_t, width - 2*wall_t, height + 0.002]);
}

Every constraint you can express as an assert() is a constraint that no longer requires manual verification. If someone changes wall_t = 0.5 (too thin to print), the build immediately stops with a clear message instead of silently producing a model that fails on the printer.


Concept 2: Privacy and AI Tools

What Happens to Files You Upload

When you use cloud-based AI tools — including the 3dm info AI description feature when it connects to a cloud model, or an external AI chat like Claude or ChatGPT — your files and prompts are processed on remote servers. Depending on the service and its privacy policy, that data may be:

  • Used to improve the AI model (potentially meaning others could see examples from your session)
  • Stored for a period of time
  • Subject to the provider’s legal obligations in their jurisdiction

For classroom learning projects, this is generally a non-issue — there’s nothing sensitive about learning how to make a parametric box. But if you’re ever working on a design that represents real intellectual property (a product idea, a client’s design, proprietary measurements), you need to understand what you’re sending and to whom.

Best practices for privacy-sensitive work:

  • Check the AI service’s data retention policy before uploading
  • Simplify or abstract the design before sending for review (remove specific dimensions, replace proprietary shapes with generic approximations)
  • Use local/offline tools for final verification of sensitive designs — the bounding box and slicer checks don’t require network access

For the purposes of this certification course, all your projects are learning work and standard cloud AI tools are appropriate. But developing the habit of thinking about this now is professional practice.


Validation Type Summary

Validation TypeWhat It ChecksReliability
3dm info bounding box & volumeExact model dimensionsDeterministic — identical every run
3dm info AI descriptionOverall shape, component layoutNon-deterministic — may vary
Slicer layer viewWall thickness, internal features, overhangsDeterministic — reliable for geometry
Physical calipersPrinted part dimensionsGround truth — most authoritative
assert() guardsParameter validity before renderDeterministic — runs at build time

Quiz — Lesson 4 (15 questions)

  1. What does 3dm info do? What two fundamentally different types of information does it provide?
  2. What is the key difference between deterministic validation and AI-based validation?
  3. Give two specific examples of information that 3dm info’s AI description cannot reliably provide.
  4. In the verification escalation chain, which level provides “ground truth” for dimensional accuracy, and why?
  5. List three common errors that AI tools make when generating OpenSCAD code.
  6. True or False: the bounding box reported by 3dm info might be slightly different each time you run it on the same file.
  7. What data privacy concern should you consider before uploading a proprietary design to a cloud AI service?
  8. What does the slicer layer view let you verify that the bounding box cannot show?
  9. What two characteristics distinguish a strong AI code review prompt from a weak one?
  10. If an AI describes your model as “a small cylindrical protrusion” and you designed it as 3.2 mm in diameter, why is this description insufficient for print verification?
  11. What is “prompt engineering” and why does it matter when asking an AI to review OpenSCAD code?
  12. Write an assert() statement that ensures a variable called layer_height is between 0.05 mm and 0.4 mm.
  13. What is the advantage of using assert() at the top of a file compared to manually checking parameter values before every build?
  14. Describe one scenario where AI validation would be genuinely useful and one where you must rely on deterministic tools instead.
  15. A classmate says “the AI said my model looked fine, so I sent it to print.” What is wrong with this approach, and what should they have done instead?

Extension Problems (15)

  1. Design a five-item verification checklist for a new 3D printed part. Include items that are deterministic and items that benefit from AI assistance. Label each.
  2. Build a “prompt library” for three common design review scenarios (mounting bracket, enclosure with lid, text embossing). Test each prompt against an AI tool and document the output quality.
  3. Run 3dm info on the same STL file five times. Document any variation in the AI description output. What does this variation tell you about using AI for precision work?
  4. Create a structured accept/reject log for one full design cycle: design → verification checklist → AI review → physical test → decision to print or revise.
  5. Research what “hallucination” means in the context of AI language models. Describe two specific ways an AI could hallucinate during a design review of OpenSCAD code.
  6. Create a set of deliberately flawed OpenSCAD files — one with a missing 0.001 offset, one with a Python-style variable reassignment, one with a thin wall below 1.2 mm. Test whether an AI code review catches each flaw.
  7. Write a one-page data privacy policy for a classroom 3D printing lab that uses cloud AI tools. What should students be required to understand before uploading files?
  8. Build a “verification script” that automatically runs 3dm build, checks the exit code, runs 3dm info, and extracts the bounding box for comparison against expected values.
  9. Research the difference between “AI-assisted” and “AI-automated” workflows. At what point does removing a human from the verification loop become risky in a manufacturing context?
  10. Design an experiment: ask three different AI tools to review the same OpenSCAD file. Document the similarities and differences in their feedback. What does this tell you about AI reliability?
  11. Build a comparison table: for five design features (bolt holes, thin walls, snap-fit gaps, embossed text, threaded inserts), identify whether AI review, slicer validation, or physical calipers is most reliable.
  12. Research and document what “manifold” means in geometry. What makes a mesh non-manifold? What are the three most common causes in OpenSCAD?
  13. Write a one-page explanation of the verification escalation chain written for a student in the 8th grade who has never heard of 3D printing. Use no technical jargon without defining it.
  14. Create an assert() suite for a parametric box design: validate width, depth, height, wall thickness, and the relationship between wall thickness and overall size. Test it with at least three invalid parameter sets.
  15. Write a short guide titled “When to Trust AI and When Not To” specifically for 3D design workflows. Include at least five specific decision rules.

References and Helpful Resources

  • OpenSCAD User Manual — Manifold and Geometry Validation — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language

  • Anthropic Prompt Engineering Guide — https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview

  • Data Privacy — Review your AI provider’s terms of service and data retention policy before submitting proprietary design files.

  • NIST AI Risk Management Framework (AI RMF 1.0) — https://www.nist.gov/system/files/documents/2023/01/26/AI%20RMF%201.0.pdf

Supplemental Resources

  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake
  • Anthropic Prompt Engineering Overview — https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview
  • NIST AI RMF — https://airc.nist.gov/Home
  • PrusaSlicer Documentation — https://docs.prusa3d.com/en/
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Extension Project and Reference Appendices

All supporting documents for Lesson 4 are included below. You do not need to open any additional files.


Appendix A: Dice, Dice, Dice — Extension Project

Estimated time: 3–6 hours

Overview

This extension project connects the verification and AI-assisted feedback skills from Lesson 4 to a physical object where design precision is directly measurable: a six-sided die. A fair die is one of the most demanding manufactured objects you can design — it requires uniform geometry, controlled mass distribution, and a randomness that can be tested statistically. The design is straightforward. The verification is where the real learning happens.

This project also inverts the lesson’s AI-skepticism lesson in a productive way: it uses AI as part of the design ideation process, then requires you to verify every claim with physical testing and statistical analysis. A die that the AI describes as “balanced and symmetric” should be tested with 100+ real rolls. If the data disagrees with the description, the data wins.

Learning Objectives

By completing this project, you will:

  • Design parametric dice in OpenSCAD with controlled geometry and mass distribution
  • Apply the verification chain from Lesson 4 to a physical fabrication outcome
  • Test durability and randomness for small, thrown objects
  • Conduct and document statistical fairness testing
  • Understand how infill, wall thickness, and pip geometry affect roll behavior

Materials

  • Computer with OpenSCAD and slicer
  • Printer and filament (PLA recommended — easy to print and dimensionally consistent)
  • A small throwing surface (book, box lid, or low-sided tray)
  • Calipers if available (for dimensional verification)

Tasks

  1. Design three distinct die variants in OpenSCAD using parameters (size, wall, infill_proxy, pip_depth, pip_r). Each variant must differ in at least one meaningful way — for example: different pip geometry (sunken vs. flat), different wall thickness, or different overall size. All three must be generated from the same parametric module by changing variables at the top of the file.

  2. Document your design decisions. For each variant, write one short paragraph explaining which parameters you changed and why you expected that change to affect fairness or durability.

  3. Print one sample of each variant. Use the same material and layer height for all three to isolate the design variable.

  4. Durability test: five throws onto a soft surface for each die. Record whether any delamination, corner chipping, or pip damage is visible after testing.

  5. Fairness test: roll each die at least 100 times on a consistent surface. Record every result in the roll data table (Appendix B). Compute the frequency of each face and compare to the expected 16.67%.

  6. Statistical analysis: calculate the deviation from expected for each face. A die within ±3% per face on 100 rolls is performing within normal random variation. A face appearing more than 20% of the time suggests a design or print bias that warrants investigation.

Probing Questions

  • How does internal infill or a hollow cavity affect mass distribution and roll randomness?
  • Which parameter change had the largest effect on fairness or durability, and why do you think that is?
  • If one face came up significantly more often than expected, what is the most likely physical cause?

Starter Code

// Parametric Six-Sided Die
// All critical dimensions are top-level parameters.
// Change these to create your three variants.

// ---- Parameters ----
die_size   = 16;     // mm — overall cube side length
wall       = 2.0;    // mm — wall thickness (increase for more durability)
pip_r      = 1.0;    // mm — radius of pip hemispheres
pip_depth  = 0.6;    // mm — how deep pips are pressed into the face
corner_r   = 1.2;    // mm — chamfer/rounding radius on die edges
$fn        = 32;     // curve resolution

// Verify printability
assert(wall >= 1.2,
  str("wall (", wall, "mm) is below minimum printable thickness (1.2mm)"));
assert(pip_r > 0 && pip_r < die_size / 6,
  str("pip_r (", pip_r, "mm) is unreasonable for this die size"));
assert(pip_depth < wall,
  str("pip_depth (", pip_depth, "mm) must be less than wall (", wall, "mm)"));

// ---- Pip Positions (for each face, relative to face center) ----
// Each face is a list of [x, y] offsets from center, in pip-spacing units.
// spacing = die_size / 5 gives a comfortable pip layout.
pip_spacing = die_size / 5;

face_1_pips = [[0, 0]];
face_2_pips = [[-1, -1], [1, 1]];
face_3_pips = [[-1, -1], [0, 0], [1, 1]];
face_4_pips = [[-1, -1], [1, -1], [-1, 1], [1, 1]];
face_5_pips = [[-1, -1], [1, -1], [0, 0], [-1, 1], [1, 1]];
face_6_pips = [[-1, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [1, 1]];

// ---- Single Pip (hemisphere subtracted from a face) ----
module pip(depth=pip_depth, r=pip_r) {
  sphere(r=r, $fn=16);
}

// ---- Pips on a face (2D positions, extruded onto face surface) ----
// This module places pips at the given positions on the +Z face of the die.
module place_pips(positions, face_z, r=pip_r, depth=pip_depth, spacing=pip_spacing) {
  for (pos = positions) {
    translate([die_size/2 + pos[0]*spacing,
               die_size/2 + pos[1]*spacing,
               face_z + r - depth])
      pip(depth, r);
  }
}

// ---- Die Body ----
module die_body() {
  // Simple cube — replace with minkowski sphere for rounded edges
  cube([die_size, die_size, die_size]);
}

// ---- Full Die with Pips Subtracted ----
module die() {
  difference() {
    die_body();

    // Face +Z (top): 1 pip
    place_pips(face_1_pips, die_size);
    // Face -Z (bottom): 6 pips (opposite of 1)
    mirror([0, 0, 1])
      place_pips(face_6_pips, 0);
    // Face +X (right): 2 pips (opposite of 5)
    rotate([0, -90, 0]) translate([0, 0, -die_size])
      place_pips(face_2_pips, die_size);
    // Face -X (left): 5 pips
    rotate([0, 90, 0])
      place_pips(face_5_pips, die_size);
    // Face +Y (front): 3 pips (opposite of 4)
    rotate([90, 0, 0]) translate([0, 0, -die_size])
      place_pips(face_3_pips, die_size);
    // Face -Y (back): 4 pips
    rotate([-90, 0, 0])
      place_pips(face_4_pips, die_size);
  }
}

die();

Notes on using this scaffold:

  • To create Variant 2, change wall and pip_depth. To create Variant 3, change die_size. Keep all other parameters the same between variants so you isolate the effect.
  • The assert() statements will catch unreasonable parameter combinations before rendering.
  • For rounded-corner dice (more realistic feel, less edge chipping), replace die_body() with a minkowski() of a smaller cube and a sphere(r=corner_r) — see the AI code gallery in Appendix D for a worked example of this technique.

Quiz Questions (from workshop)

  1. What parameter controls wall thickness in your .scad file?
  2. Name one method to increase a die’s impact resistance without changing its overall size.
  3. How would you test a die for randomness? What is the minimum number of rolls for a meaningful result?
  4. Why might a hollow die behave differently from a solid one of the same external dimensions?
  5. What is a simple visual sign of print-layer delamination on a die?
  6. True or False: A perfectly fair die must have uniform weight distribution throughout, including the internal structure.
  7. Describe two design approaches for rendering the face numbers: one using difference() to create sunken pips, one using linear_extrude() for raised numbers.
  8. Your die lands on face 1 significantly more often than any other face in 100 rolls. Name two possible physical causes and describe how you would diagnose each.
  9. If you increase infill from 15% to 50%, what is the primary effect? (A) Dramatically longer print time, same weight (B) Significantly longer print time and higher weight (C) Same weight, different surface finish. Answer: B
  10. Explain why a fair die is an excellent test of manufacturing precision. How does this project connect design decisions to real-world measurable outcomes?

Appendix B: Dice, Dice, Dice — Student Documentation Template

Author: ________________ Date: __________ Description: Design parametric 3D-printed dice and test for fairness through physical testing and statistical analysis.


Design Concept

  • Overall die size and material:
  • How will you address uniform weight distribution in your design?
  • What design details will differentiate your three variants?

Design Specifications

ParameterVariant 1Variant 2Variant 3
die_size (mm)
wall (mm)
pip_r (mm)
pip_depth (mm)
corner_r (mm)
Infill % (slicer)
Estimated mass (g)
Actual mass (g)

Variant 1 design rationale (one paragraph — what did you change and what outcome did you expect?):

Variant 2 design rationale:

Variant 3 design rationale:


Dimensional Verification

Run 3dm build then 3dm info on each variant. Record the deterministic output:

MeasurementVariant 1Variant 2Variant 3
Bounding box X (mm)
Bounding box Y (mm)
Bounding box Z (mm)
Volume (mm³)
Expected die_size (mm)
Deviation from expected (mm)

If any dimension deviates by more than 0.5 mm from die_size, investigate before printing.


Durability Test

Five throws per variant onto a soft surface (book cover, box lid, fabric).

ThrowVariant 1 — ObservationsVariant 2 — ObservationsVariant 3 — Observations
1
2
3
4
5

Post-durability inspection:

  • Any layer delamination visible? (Variant 1 / 2 / 3):
  • Any corner chipping? (Variant 1 / 2 / 3):
  • Any pip damage? (Variant 1 / 2 / 3):

Fairness Testing — Roll Results

Complete this table for your best-performing variant (or all three if time permits). Minimum 100 rolls per die tested.

Variant tested: ____ Total rolls: ____ Date: ____ Surface used: ____

FaceTally (mark each roll)FrequencyPercentageExpected (16.67%)Deviation
1%16.67%
2%16.67%
3%16.67%
4%16.67%
5%16.67%
6%16.67%
Total100100%100%

Statistical Analysis

Maximum deviation from expected (the highest “Deviation” value in your table): ____ %

Interpretation:

  • Deviation ≤ 3% on all faces: Normal random variation — die performs within acceptable range
  • Deviation 3–5% on one face: Mild bias — investigate print quality and pip geometry
  • Deviation > 5% on any face: Significant bias — design or print issue warrants redesign

Your conclusion (is this die fair within statistical tolerance?):

Most frequent face: ____ Least frequent face: ____

If the die shows bias, what physical cause do you suspect? (Pip depth on the heavy face? Bed adhesion producing a flatter bottom? Asymmetric corner rounding?):


Reflections

  1. Were you surprised by the fairness test results? Did the die perform better or worse than you expected?

  2. Which design parameter had the largest effect on the test outcome, and what does that tell you about the physics of the die?

  3. What would you change in a fourth iteration to improve fairness?

  4. What did this project teach you about the gap between a design that looks correct on screen and one that performs correctly in the physical world?


Attachments Checklist

  • .scad file with parametric die module (all three variants producible from one file)
  • Photo of all three printed die variants
  • Raw roll data tally sheet (the actual marks for each roll)
  • Completed frequency and statistical analysis table
  • Dimensional verification output from 3dm info for each variant

Teacher Feedback

CategoryScore (0–3)Notes
Problem & Solution — dice print successfully; fairness testing conducted rigorously
Design & Code Quality — parametric module produces all three variants; assert() used; code is commented
Documentation — roll data complete; statistical analysis accurate; reflections show understanding
Total (0–9)

Appendix C: Dice, Dice, Dice — Instructor Reference

Project Context

This extension project reinforces the lesson’s central theme — trusting data over descriptions — by making the verification stakes concrete and measurable. The fairness of a printed die is something a student can test with their own hands. A die that the AI describes as “perfectly symmetric” but lands on face 1 thirty percent of the time is an immediate, visceral demonstration of why physical testing matters.

The chi-squared test is mentioned in the teacher rubric but is not required for baseline completion. Students who complete it should receive recognition for the additional rigor; students who compute simple percentage deviation are satisfying the core requirement.

Key Learning Points to Reinforce

Verification is empirical, not descriptive. The workflow mirrors Lesson 4’s verification chain directly: deterministic check (3dm info bounding box), then visual check (slicer layer view), then physical test (the roll data). A student who prints without running 3dm info first has skipped the deterministic layer.

Parametric design means one module, multiple variants. Students who create three separate .scad files (one per variant) miss the core parametric design goal. The correct approach is a single file where changing variables at the top produces each variant. This is directly assessable in the code review.

Statistical fairness has a physical explanation. When a face appears too frequently, the most common causes are: (1) pip depth asymmetry — faces with fewer/shallower pips have more mass on that face, causing it to face down more often; (2) bed adhesion flattening the bottom face slightly during printing; (3) infill asymmetry if the model origin isn’t centered. Students should be guided toward diagnosing the cause, not just noting the result.

Constraints (Enforce These)

  • All three variants must be produced from a single parametric .scad file
  • assert() statements must validate key parameters (wall thickness minimum, pip depth less than wall)
  • Minimum 100 rolls for fairness testing — 50 rolls is not statistically meaningful
  • Raw roll data (the actual tally) must be submitted, not just the summary table

Assessment Notes

Strong submissions show: roll data with a tally sheet (not just a filled-in table), a physical explanation for any bias observed, and a genuine iteration — the student changed something between variants because of a hypothesis, not randomly.

Common weak areas: Single-variant testing because “it looked fine,” statistical tables with numbers that don’t add up to 100%, and designs where pip depth equals wall thickness (causing holes through the die). The assert() in the starter code catches the last one at render time.

Extension for advanced students: A formal chi-squared goodness-of-fit test. With 100 rolls and 6 faces, the critical value at p=0.05 significance is χ² = 11.07 (5 degrees of freedom). If the computed chi-squared exceeds this value, the die has a statistically significant bias. This is a meaningful cross-curricular mathematics application.


This appendix expands on the lesson’s AI discussion and provides concrete debuggable examples of typical AI mistakes. Use the flawed examples as debugging exercises — fix each one, then run 3dm build3dm info → slicer layer view to confirm the fix.


D1 — Advantages of AI in OpenSCAD Development

Rapid ideation and scaffolding. AI can convert a natural-language description into a first-draft parametric scaffold quickly. This is useful for getting a starting structure, but the generated code must always be verified — never sent directly to print.

Accessibility support. Natural-language descriptions via 3dm info make model verification more accessible to visually impaired makers who cannot rely on visual inspection of the 3D preview. AI-assisted verbal description of model geometry can substitute for visual inspection when implemented carefully.

Promptable code review. A well-structured prompt asking an AI to review OpenSCAD code for boolean pitfalls, coplanar faces, and thin walls can catch issues that a visual scan might miss — as long as you verify any issues it raises rather than trusting its “all clear.”

Iteration speed. AI can propose parameterizations and printability tips rapidly, letting you evaluate more design directions before committing to print. The key is that you verify deterministically; AI accelerates the ideation, not the verification.


D2 — Disadvantages and Risks

Non-determinism. The same prompt given twice may produce different answers. AI is not a source of truth for design specifications or dimensional requirements.

No geometric guarantees. AI generates descriptions based on inference from rendered images or code text — it does not compute solid geometry. It can describe a model as correct that has non-manifold geometry or zero-thickness walls that will fail in the slicer.

Standards and tolerances gaps. AI may suggest clearances, wall thicknesses, or print settings that contradict established practice for your specific printer and material. Always check AI suggestions against the lesson’s reference values.

Hallucinations. AI tools sometimes generate code using functions that do not exist in OpenSCAD, such as rounded_cube(), fillet3d(), or bevel_edge(). These functions will cause a compile error if you attempt to use them. The AI is not aware it has invented them.

Privacy and IP exposure. Cloud AI tools may retain uploaded files or use them for training data, depending on their terms of service. Before uploading a design file to any cloud AI service, check the provider’s data retention and privacy policy. In a classroom context, no personally identifiable or commercially sensitive designs should be uploaded without explicit instructor approval.


Use each example below as a debugging exercise. Identify the flaw, fix it, and verify the fix with 3dm build followed by 3dm info.


Example 1: Hallucinated Convenience Function

The AI claims OpenSCAD has a rounded_cube() built-in. It does not.

// ❌ FLAWED — rounded_cube() does not exist in OpenSCAD
module enclosure() {
  rounded_cube(size=[60, 40, 20], r=3);
  translate([10, 10, 0]) cylinder(h=20, r=2, center=false);
}
enclosure();

Fixed version — use minkowski() with a sphere() instead:

// ✅ CORRECT — native minkowski approach for rounded corners
module rounded_box(x=60, y=40, z=20, r=3) {
  minkowski() {
    cube([x - 2*r, y - 2*r, z - 2*r]);
    sphere(r=r, $fn=32);
  }
}
rounded_box();

What to learn from this: If an AI gives you OpenSCAD code that uses a function name you haven’t seen before, look it up in the OpenSCAD documentation before using it. A compile error at render time is the warning sign.


Example 2: Coplanar Boolean (Missing 0.001 Offset)

When the subtracted shape shares an exact face with the outer shape, some renderers produce Z-fighting artifacts and unreliable geometry.

// ❌ FLAWED — bottom faces are coplanar (Z=0 on both shapes)
difference() {
  cube([30, 30, 10]);
  translate([5, 5, 0]) cube([20, 20, 10]);
}

Fixed version — extend the subtracted shape by 0.001 mm past each coplanar face:

// ✅ CORRECT — 0.001 overshoot on both Z faces
difference() {
  cube([30, 30, 10]);
  translate([5, 5, -0.001]) cube([20, 20, 10 + 0.002]);
}

What to learn from this: Any time a difference() subtraction should go all the way through a face, add a 0.001 mm overshoot. This is a mechanical rule, not an approximation — apply it consistently.


Example 3: Wrong Transform Order (Misplaced Holes)

Rotate-then-translate and translate-then-rotate produce different results. AI often gets this wrong.

// ❌ FLAWED — rotate applied before translate; hole ends up in wrong position
module bracket(width=40, height=20, th=3, hole_r=3) {
  difference() {
    cube([width, th, height]);
    translate([width/2, th/2, height/2])
      rotate([90, 0, 0])
        cylinder(h=th, r=hole_r, center=true);
  }
}
bracket();

Fixed version — the translate sets the center, then the rotate orients correctly:

// ✅ CORRECT — translate to center, then rotate into the correct plane
module bracket(width=40, height=20, th=3, hole_r=3) {
  difference() {
    cube([width, th, height]);
    translate([width/2, th/2, height/2])
      rotate([90, 0, 0])
        cylinder(h=th + 0.002, r=hole_r, center=true);
  }
}
bracket();

What to learn from this: Always check hole placement in the slicer layer view. The AI’s code may look syntactically correct but produce geometry that is correct only for a specific, unverified set of assumptions about how transforms compose.


Example 4: Procedural Variable Reassignment

OpenSCAD is a declarative language — variables are not mutable. AI trained on Python, JavaScript, or other imperative languages sometimes generates code that assumes variables can be updated.

// ❌ FLAWED — OpenSCAD does not allow reassignment of variables
width = 60;
width = width + 10; // This silently uses the LAST assignment; the first is ignored
cube([width, 20, 10]);

Fixed version — use distinct names for derived values:

// ✅ CORRECT — derive a new variable from the base value
base_w  = 60;
final_w = base_w + 10;
cube([final_w, 20, 10]);

What to learn from this: In OpenSCAD, a variable that appears assigned twice will use the last assignment for the entire file — including places that appear before the second assignment in the code. This is a source of subtle bugs. Always use a new name for derived values.


Example 5: Unsafe Parameter Limits (Geometry Inversion)

AI-generated modules often lack parameter validation. When given edge-case values, the geometry inverts silently.

// ❌ FLAWED — no validation; wall=12 on a w=20 box inverts the geometry
module box(w=30, d=30, h=20, wall=3) {
  difference() {
    cube([w, d, h]);
    translate([wall, wall, -0.001])
      cube([w - 2*wall, d - 2*wall, h + 0.002]);
  }
}
box(w=20, d=20, h=15, wall=12); // wall larger than half the width — silent failure

Fixed version — add assert() to catch invalid combinations:

// ✅ CORRECT — assert() catches invalid parameters before geometry is computed
module box(w=30, d=30, h=20, wall=3) {
  assert(w > 0 && d > 0 && h > 0, "All dimensions must be positive");
  assert(wall > 0 && wall < min(w, d) / 2,
    str("wall (", wall, "mm) must be less than min(w,d)/2 = ", min(w,d)/2, "mm"));
  difference() {
    cube([w, d, h]);
    translate([wall, wall, -0.001])
      cube([w - 2*wall, d - 2*wall, h + 0.002]);
  }
}
box(w=20, d=20, h=15, wall=12); // will halt with a clear error message

What to learn from this: assert() is your safety net for parametric designs. Any relationship between parameters that could produce invalid geometry should have an assert() checking it. This is especially important for designs you share with others.


Example 6: Hallucinated Text Function + Misplaced Emboss

Two compound errors: a function that doesn’t exist (fillet_text()), and a text position that extends outside the model face.

// ❌ FLAWED — fillet_text() does not exist; second translate puts text outside the body
difference() {
  cube([80, 40, 6]);
  translate([0, 0, 0])
    fillet_text("RYAN", size=10, radius=1); // bogus function
  translate([70, 20, 3])
    linear_extrude(2) text("RYAN", size=10); // misplaced — extends off the edge
}

Fixed version — use standard text() with linear_extrude(), centered on the face:

// ✅ CORRECT — centered debossed text using standard OpenSCAD functions
module top_deboss(txt="RYAN", size=10, depth=1) {
  translate([40, 20, 6 + 0.001])  // position at center of top face
    linear_extrude(height=depth)
      text(txt, size=size, halign="center", valign="center");
}

difference() {
  cube([80, 40, 6]);
  top_deboss();
}

What to learn from this: Text positioning requires knowing the face center, not just a rough location. Use halign="center" and valign="center" with a translate to the face center. The 0.001 mm overshoot on the Z translate ensures the subtracted text breaks through the face cleanly.


Example 7: Zero Clearance on a Fitted Lid

AI-generated box and lid designs often omit clearance, making the lid impossible to remove after printing.

// ❌ FLAWED — zero clearance means the lid walls will fuse to the box walls
module box_outer(sz=[60, 40, 20], wall=2) { cube(sz); }
module box_inner(sz=[60, 40, 20], wall=2) { cube([sz[0]-2*wall, sz[1]-2*wall, sz[2]]); }

difference() {
  box_outer();
  translate([2, 2, -0.001]) box_inner(); // clearance = 0; lid won't come off
}

Fixed version — add a clearance parameter to the socket dimensions:

// ✅ CORRECT — clearance creates the physical gap needed for the lid to fit and move
module box_with_clearance(w=60, d=40, h=20, wall=2, clr=0.25) {
  assert(clr > 0 && clr < 1.0, "Clearance should be between 0 and 1mm for most FDM fits");
  difference() {
    cube([w, d, h]);
    translate([wall + clr, wall + clr, -0.001])
      cube([w - 2*(wall + clr), d - 2*(wall + clr), h + 0.002]);
  }
}
box_with_clearance();

What to learn from this: FDM-printed parts that are designed to fit together always need clearance. A nominal 0mm gap at design time produces a stuck or impossible fit after printing. Typical clearance for a slip fit is 0.2–0.3 mm; for a press fit, 0.0–0.1 mm. This topic is covered in depth in Lesson 8. -e


Safety Protocols and the Physical Fabrication Interface

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

Every lesson so far has been entirely digital: code on a screen, commands in a terminal, virtual geometry. Now we’re moving into the physical world. 3D printers are machines that get very hot, draw substantial electrical current, and produce airborne particles and vapors. This lesson exists because these machines are genuinely safe when you know what you’re doing, and genuinely dangerous when you don’t.

The good news is that 3D printing safety is not complicated. The hazards are well-understood, the mitigations are straightforward, and the incidents that do happen are almost always caused by ignoring simple rules. The goal of this lesson is to make sure you know the rules and understand why they exist — not just as things to memorize for a quiz, but as habits you can apply in any shop or makerspace you ever work in.


Learning Objectives

By the end of this lesson you will be able to:

  • Identify and apply the Hierarchy of Controls for 3D printing hazards
  • Apply fire, electrical, and fume safety protocols for FDM printing
  • Understand filament-specific hazards and safe material handling
  • Follow a safe printer startup, monitoring, and shutdown sequence
  • Select appropriate filament materials for given projects
  • Use pre-flight build scripts to estimate cost before committing to a print
  • Design parts that minimize safety risks during printing

Concept 1: The Hierarchy of Controls

Why We Don’t Just “Be Careful”

When it comes to workplace and lab safety, the common advice “just be careful” is the least effective approach available. It relies entirely on individual attention, and attention is inconsistent — everyone gets tired, distracted, or hurried sometimes. Professional safety systems are designed to work even when individual attention lapses.

The Hierarchy of Controls is a framework developed by OSHA (the U.S. Occupational Safety and Health Administration) and adopted worldwide. It ranks safety strategies from most effective to least effective, and it says: apply the most effective strategy you can afford, and layer additional strategies below it.

The five levels, from most to least effective:

1. Elimination — Remove the hazard entirely. If a filament requires a sealed enclosure with active filtration and you’re in an open classroom, the safest choice is simply not to use that filament. If a print requires supports made from difficult material, redesign the print to not need supports. Elimination always wins.

2. Substitution — Replace the hazard with a less dangerous one. Use PLA instead of ABS. Use a PEI spring steel bed instead of a glass bed that can shatter. Substitution keeps the functionality while reducing the risk.

3. Engineering Controls — Build protection into the environment. A fume enclosure with a HEPA + activated carbon filter. Thermal runaway protection in the printer firmware. A smoke detector mounted above the printer. These controls work automatically without relying on human behavior.

4. Administrative Controls — Rules, procedures, and training. The startup checklist, the monitoring schedule, the training program you’re in right now. Administrative controls are less reliable than engineering ones because they depend on people following rules consistently.

5. Personal Protective Equipment (PPE) — Gloves, goggles, respirators. PPE is the last resort — it protects one person, it can fail or be used incorrectly, and it doesn’t actually remove the hazard. Always apply higher-level controls first and use PPE as a supplement.

The key insight: many beginners think that putting on gloves and goggles makes them safe. In the hierarchy, PPE is the weakest protection. Real safety comes from eliminating or substituting hazards, and then engineering the remaining risks away. PPE is what you use when those options aren’t available.


Step 1 — Fire and Electrical Safety

The Golden Rule

Never leave an FDM printer completely unattended during the first layer. Print failures most often happen at the start — the first layer either bonds to the bed or it doesn’t. If it doesn’t bond and nobody is watching, the printer may continue for hours, dragging filament across the bed in a mess called “spaghetti” that can tangle around the print head, cause jams, or — in rare worst cases — create a fire hazard.

Be present and watching for at least the first 15 minutes of every print. For long prints, check in every 30 minutes or set up remote monitoring via OctoPrint or a camera.

Fire Hazards

Fire risk in FDM printing comes from two main sources. First, electrical failure: wiring that cracks from repeated movement, loose connections at terminal blocks, or a faulty temperature sensor that allows the heater to run without limit. Second, filament accumulation: plastic that melts and collects on the hot nozzle can sometimes ignite if the build-up becomes large enough.

Fire safety protocols:

  • Keep a Class ABC fire extinguisher within arm’s reach of every printer
  • Never run the printer while away from the building
  • Keep the print area clear of flammable materials: paper, fabric, solvent containers
  • Mount a smoke detector directly above the printer so rising smoke reaches it quickly
  • Know where the power switch is before you start — cutting power is the first response to any emergency
  • If smoke appears: cut power immediately, do not try to continue the print, and report the incident

Electrical Safety

  • Use a surge protector to protect the printer’s control board from voltage spikes
  • Inspect all wiring periodically, especially the flexible cable bundle that runs to the heated bed — this bundle flexes with every print and can crack the insulation over time

Warning

Thermal runaway protection must be enabled. This firmware feature monitors the temperature sensor and shuts the heater off if the temperature climbs unexpectedly or the sensor fails. A printer without thermal runaway protection can overheat catastrophically. Never disable this protection. If your printer doesn’t have it, do not use it.

  • Never open the power supply enclosure or work on any electrical component while the printer is plugged in. The power supply contains mains voltage (120V or 240V) that can kill.

Step 2 — Fume Safety

Why Fumes Matter

All FDM printing produces some airborne emissions. These fall into two categories: particulates (tiny plastic particles, especially ultrafine particles below 0.1 microns) and VOCs (volatile organic compounds — chemical vapors that off-gas from the hot plastic). Both can affect respiratory health with repeated exposure, and the risk varies significantly by material.

MaterialFume RiskRequired Mitigation
PLALowGood room ventilation (open window or HVAC on)
PETGLow–MediumActive ventilation; avoid enclosed spaces without air exchange

Warning

ABS and ASA are NOT safe for open classrooms without a dedicated fume enclosure with HEPA + activated carbon filtration. Do not print ABS or ASA in any space without proper exhaust infrastructure.

| ABS | High | Dedicated fume enclosure with HEPA + activated carbon filter required; NOT safe for open classrooms | | ASA | High | Same as ABS | | TPU | Medium | Active ventilation; keep nozzle temperature at the minimum needed | | Resin (SLA/MSLA) | Very High | Full enclosure; nitrile gloves; UV-blocking goggles; no open-workspace use |

The Safe Choice: PLA

Tip

PLA is the safest classroom filament available. Made from bio-derived sources, it prints at low temperatures (190–220°C) and produces the lowest emissions of any common FDM material. Default to PLA for any project where mechanical requirements don’t specifically demand something else.

What “Good Ventilation” Actually Means

“Good ventilation” means that the air in the room is actively exchanging with outside air. This is not the same as “a window that’s crackable.” Active ventilation means:

  • A window open with a fan pulling air through the room, or
  • An HVAC system that is running and moving air, not just recirculating internal air

If you’re printing ABS or ASA, room ventilation is not sufficient. You need an enclosure with a filtered exhaust system — a box around the printer with an internal fan that pulls fumes through a HEPA filter (for particles) and an activated carbon filter (for VOCs) before exhausting outside or into a large ventilated space.


Step 3 — Material Selection

Choosing the Right Filament

The right material for a project depends on what the part needs to do and where it will be used. This table gives you a practical guide:

FilamentStrengthFlexibilityHeat ResistancePrint DifficultyBest Uses
PLAMediumRigidLow (softens at 50–60°C)EasyPrototypes, display models, artwork, educational parts
PETGMedium-HighSlightly flexibleMedium (75–80°C)Easy–MediumFunctional parts, food-adjacent applications, water contact
ABSHighSemi-rigidHigh (85–100°C)HardHot environments, automotive interiors, post-processing (acetone smoothing)
TPUMediumVery flexibleMediumMediumGaskets, grips, phone cases, flexible joints
NylonVery HighFlexibleHighHardMechanical parts, gears, load-bearing functional parts
ASAHighSemi-rigidVery High (90°C+)HardOutdoor use, UV-exposed parts

What “Hard” to Print Actually Means

When a material is listed as “hard,” that means it requires one or more of the following: a higher nozzle temperature, a heated enclosure to prevent warping, special bed adhesion (glue stick, hairspray, specialized plates), slower print speeds, or more careful tuning of retraction settings. Starting with a difficult material before you have PLA dialed in is a recipe for frustration and wasted filament.

Tip

The practical material rule: use PLA until you have a specific functional reason not to. Need better heat resistance? Try PETG next. Reserve ABS and specialty materials for when you have the appropriate safety infrastructure.

PLA and Sustainability — A Realistic Picture

PLA is often marketed as “biodegradable” and “eco-friendly.” These claims deserve some scrutiny. PLA is bio-derived — made from fermented plant starch rather than petroleum — which reduces its carbon footprint somewhat compared to petroleum plastics. But PLA only biodegrades under very specific industrial composting conditions (temperatures above 58°C sustained for weeks). It does not break down in a home compost bin or a landfill.

The most sustainable approach to FDM printing is not any particular material — it’s designing durable parts that don’t need to be reprinted, using the minimum infill that meets your mechanical requirements, and avoiding test prints you don’t need (which is exactly why this course emphasizes verification before printing).


Step 4 — Estimating Print Cost Before You Print

Always Estimate First

Tip

Always estimate filament cost and print time before sending a model to print. For small parts the cost is trivial, but large high-infill parts can cost several dollars and several hours — time you can’t recover if the part needs revision.

The estimate formula from Lesson 1 applies here:

mass (grams)  = (volume_mm³ ÷ 1000) × filament_density_g_per_cm³
cost ($)      = mass × (spool_price_$ ÷ spool_weight_g)

The preflight scripts below automate this calculation and require you to confirm before proceeding.

Pre-Flight Cost Check Scripts

Linux / macOS (bash):

#!/bin/bash
set -e

3dm build
INFO=$(3dm info)
echo "$INFO"

# Extract volume from 3dm info output
VOLUME=$(echo "$INFO" | grep -oP '(?<=Volume:\s)\d+\.?\d*')
if [ -z "$VOLUME" ]; then
  echo "ERROR: Could not parse volume from 3dm info output"
  exit 1
fi

DENSITY=1.24    # g/cm³ — PLA density (change for other materials)
COST_PER_G=0.02 # $/g  — adjust for your spool price

MASS=$(echo "$VOLUME $DENSITY" | awk '{printf "%.1f", ($1/1000)*$2}')
COST=$(echo "$MASS $COST_PER_G" | awk '{printf "%.2f", $1*$2}')

echo ""
echo "=== PRE-FLIGHT SUMMARY ==="
echo "Volume:   ${VOLUME} mm³"
echo "Mass:     ${MASS} g  (PLA @ ${DENSITY} g/cm³)"
echo "Filament: \$${COST}  (@ \$${COST_PER_G}/g)"
echo ""
echo "Proceed? [y/N]"
read CONFIRM
if [ "$CONFIRM" != "y" ]; then
  echo "Cancelled."
  exit 0
fi
echo "Approved. Send to slicer."

Windows (PowerShell):

3dm build
$info = 3dm info
Write-Host $info

$volumeMatch = $info | Select-String -Pattern "Volume:\s+([\d.]+)"
if (-not $volumeMatch) { Write-Error "Could not parse volume"; exit 1 }
$volume = [double]$volumeMatch.Matches.Groups[1].Value

$density  = 1.24    # PLA
$costPerG = 0.02
$mass     = ($volume / 1000) * $density
$cost     = $mass * $costPerG

Write-Host ""
Write-Host "=== PRE-FLIGHT SUMMARY ==="
Write-Host ("Volume:   {0:F0} mm3" -f $volume)
Write-Host ("Mass:     {0:F1} g  (PLA)" -f $mass)
Write-Host ("`$Filament: {0:F2}" -f $cost)
Write-Host ""
$confirm = Read-Host "Proceed? [y/N]"
if ($confirm -ne "y") { Write-Host "Cancelled."; exit 0 }
Write-Host "Approved. Send to slicer."

Step 5 — The Printer Startup Checklist

Before Every Print Session

Use this checklist before starting any print. It takes about 5 minutes and prevents the most common causes of print failure.

PRINTER STARTUP CHECKLIST
□ Bed level verified (run auto-level, or manually check at all four corners)
□ Build plate clean (wipe with IPA — remove finger oils and dust)
□ Nozzle cleared (cold pull if returning from more than a day idle)
□ Filament loaded and extruding cleanly (run 50mm manual extrude purge)
□ First layer height set correctly (0.2mm gap typical for 0.4mm nozzle)
□ Print fan operational (watch it spin up at the start)
□ Workspace clear of flammable materials
□ You will remain present for the first 15 minutes of the print
□ Power switch is accessible and you know where it is

Why Each Item Matters

Important

Bed leveling is the single most critical setting for successful prints. A bed that is just 0.1 mm too high or too low can cause every print to fail. Always verify leveling before each print session. Most modern printers have automatic bed leveling (ABL), but you should still understand how it works and check that it’s running correctly.

Clean build plate prevents adhesion failures. Skin oils from touching the plate are invisible but dramatically reduce how well plastic sticks. An isopropyl alcohol (IPA) wipe before every print takes 30 seconds and prevents a common failure mode.

Cold pull (nozzle clearing) removes degraded filament from inside the nozzle. Heat the nozzle to print temperature, push some filament through, then let it cool to about 90°C and pull the filament out firmly. The end of the pulled filament should bring out any debris or degraded material from inside the hot end.

Filament loaded correctly means the extruder is feeding without clicking or skipping, the filament is straight in the Bowden tube (if present), and the purge line at the start of the print flows smoothly with no bubbles or gaps.


Step 6 — Monitoring During Prints

What to Watch For

Checking in periodically during a print takes only a few seconds each time and lets you catch problems early. A problem caught at layer 10 is a minor inconvenience. The same problem discovered at layer 100 means you’ve wasted 90 layers of material and print time.

Warning

Spaghetti is the most common print failure: the part lifts off the bed and the nozzle drags filament through the air. If you see this, pause or cancel the print immediately — catching it at layer 10 is a minor inconvenience; catching it at layer 100 wastes 90 layers of material and time.

Caution

Layer shifts (horizontal displacements in the print) usually indicate a mechanical problem — belt tension, loose pulley, or a motor skipping steps. Cancel the print and diagnose the cause before trying again.

Nozzle clog — the extruder starts making a clicking or ticking sound as the gear slips because material isn’t flowing. Filament may start grinding. Pause the print and clear the clog before restarting.

Stringing — thin wisps of filament connecting different parts of the print. Usually a retraction or temperature setting issue rather than an emergency, but it may require post-processing cleanup.

Warning

Smoke is an immediate emergency. Cut power immediately. Do not attempt to continue or diagnose while the printer is running. Notify your instructor. Do not restart the printer until the cause has been fully identified and corrected.


Step 7 — Safe Shutdown and Part Removal

The Right Way to End a Print

A print ending doesn’t mean the work is done. Follow these steps after every print:

Caution

Wait for the nozzle to cool below 50°C before reaching anywhere near the hot end. The nozzle can reach 200°C+ during printing and retains heat for several minutes after shutdown.

  1. Wait for the nozzle to cool below 50°C before reaching anywhere near the hot end.

  2. Wait for the bed to cool below 30°C before removing the part. Parts printed on a hot bed can warp slightly if removed while the bed is still warm. Many PEI-coated beds release parts naturally as they cool — you may not even need tools.

  3. Use a spatula or palette knife to gently separate the part from the build plate. Never force parts off with your fingers — the edge of a part against a spring steel bed can cut skin. Apply the spatula at a low angle and use a gentle rocking motion.

Note

Store filament in a sealed bag with desiccant. Filament absorbs moisture (hygroscopy), causing bubbling, popping sounds, and reduced mechanical properties during extrusion. This is especially critical for Nylon and PETG. A silica gel desiccant packet in a ziplock bag is sufficient for short-term storage.


Concept 2: Design for Printability and Safety

Your Design Choices Affect Safety

The decisions you make in OpenSCAD directly affect how safe and reliable the printing process will be. Good design doesn’t just mean a part that looks right — it means a part that prints reliably without requiring dangerous materials, excessive supports, or heroic printer tuning.

Minimize overhangs. Any geometry that extends more than about 45° from vertical needs supports — temporary scaffolding that the printer adds automatically. Supports increase print time, use more material, often leave rough marks where they’re removed, and increase the risk of print failure due to tangled support material. Good design reorients parts or modifies geometry to eliminate or reduce overhangs.

Caution

Minimum wall thickness for a 0.4 mm nozzle: walls below 0.8 mm (2× nozzle width) may not print reliably, and walls below ~0.8 mm may be omitted entirely by the slicer. Use at least 1.2 mm (3× nozzle width) for any structural wall.

Use the safest material that meets requirements. If PLA is strong enough, use PLA. Don’t introduce PETG, ABS, or specialty materials unless you have a specific reason and the appropriate safety infrastructure.

Encode printability constraints in your code:

// Printability constants — these drive safe design decisions
wall_min     = 1.2;    // mm — minimum wall for 0.4mm nozzle (3× nozzle width)
hole_min_r   = 1.5;    // mm — minimum hole radius for reliable circular holes
clearance    = 0.2;    // mm — fitting clearance between mating faces
overhang_max = 45;     // degrees — maximum overhang without supports

module printable_box(w, d, h, wall=2) {
  // Validate against printability limits
  assert(wall >= wall_min, str("wall (", wall, "mm) must be >= ", wall_min, "mm"));
  assert(w > 2 * wall, "width must be greater than two wall thicknesses");
  assert(d > 2 * wall, "depth must be greater than two wall thicknesses");

  // Open-top box: no overhangs on the inside
  difference() {
    cube([w, d, h]);
    translate([wall, wall, wall])
      cube([w - 2*wall, d - 2*wall, h]);  // open at top — no overhang required
  }
}

printable_box(50, 40, 30);

Exercises

Exercise 5.1: Run 3dm info on your model from Lesson 3. Calculate the material cost in PLA and in PETG (density 1.27 g/cm³). If PLA spools cost $20/kg and PETG spools cost $25/kg, what is the cost difference for your part?

Exercise 5.2: Write a pre-flight script (bash or PowerShell) that builds your model, reports the estimated cost, and requires a y confirmation before proceeding.

Exercise 5.3 (Advanced): Modify the pre-flight script to accept a --material argument (options: pla, petg, abs, tpu) and calculate cost using the correct density for the selected material.


Quiz — Lesson 5 (15 questions)

  1. What are the five levels of the Hierarchy of Controls, from most to least effective?
  2. Why is Elimination considered the most effective safety control?
  3. Which filament requires a dedicated fume enclosure with HEPA + activated carbon filtration and is NOT recommended for open classrooms?
  4. At what temperature should you wait before removing a print from the bed?
  5. What should you do immediately if you see smoke coming from your 3D printer?
  6. Give three reasons why PLA is considered the safest classroom filament.
  7. What is the minimum reliable wall thickness for a 0.4 mm nozzle, and why does this minimum exist?
  8. What is the purpose of storing filament with desiccant?
  9. True or False: It is safe to leave a 3D printer completely unattended for hours once the first layer has printed successfully.
  10. What is “spaghetti” in the context of a 3D printing failure, and what causes it?
  11. What is thermal runaway protection, and why is it critical that it remain enabled?
  12. What are the two types of airborne emissions from FDM printing, and which filaments produce the most hazardous levels of each?
  13. Describe one engineering control and one administrative control you could implement in a classroom 3D printing lab.
  14. Explain why minimizing overhangs in your design is both a safety consideration and a quality consideration.
  15. A student wants to print a car dashboard mount in ABS because it will be in a hot car. The classroom has no fume enclosure. Using the Hierarchy of Controls, what recommendations would you make?

Extension Problems (15)

  1. Create a material selection flowchart that guides a user from mechanical requirements to the safest filament that meets them.
  2. Conduct a ventilation assessment of your classroom or makerspace. Document air exchange methods, window locations, and any existing filtration.
  3. Write a Standard Operating Procedure (SOP) for ABS printing that includes all required safety equipment and ventilation infrastructure.
  4. Design and describe a “first layer test tile” — a 100 × 100 × 0.4 mm flat tile — and explain how you’d use it to verify bed leveling.
  5. Build a parametric filament storage clip in OpenSCAD: a clip that holds the free end of a filament spool. Parameters: filament diameter, clip width.
  6. Research OSHA’s published guidance on VOC exposure in 3D printing environments. Summarize the key recommendations.
  7. Compare the Safety Data Sheets (SDS) for PLA and ABS filament from two manufacturers. Document differences in recommended exposure limits and PPE.
  8. Design a simple printer enclosure in OpenSCAD: four walls, a front door opening, and a top panel with a circular vent hole. Document the parametric variables.
  9. Create a safety poster covering the five most important 3D printing safety rules, organized using the Hierarchy of Controls framework.
  10. Write a one-page risk assessment for a new FDM printer being added to a classroom.
  11. Design and describe a parametric filament moisture indicator holder: a small box that holds a humidity indicator card inside a resealable filament storage bag.
  12. Build a “print monitoring log” template: a paper form with columns for time, nozzle temperature, bed temperature, layer number, visual observations, and action taken.
  13. Research the difference between particle emissions and VOC emissions from FDM printing. Which is considered more hazardous at typical classroom distances from the printer?
  14. Design a parametric build plate corner protector: a small clip that attaches to the edge of a glass or spring steel build plate to protect it from spatula damage.
  15. Write a hypothetical “near-miss incident report” for a fictional 3D printing incident using a standard workplace incident report format (date, location, description, contributing factors, corrective actions).

References and Helpful Resources

  • OSHA Hierarchy of Controls — https://www.osha.gov/hierarchy-of-controls / NIOSH — https://www.cdc.gov/niosh/topics/hierarchy/default.html

  • UL Research Institutes — 3D Printing Emissions Study — https://www.ul.com/news/ul-research-institutes-releases-3d-printing-emissions-study

  • NIOSH Science Blog — Health and Safety Considerations for 3D Printing — https://blogs.cdc.gov/niosh-science-blog/2020/05/14/3d-printing/

  • PrusaSlicer Documentation — https://docs.prusa3d.com/en/

  • All3DP Filament Types — https://all3dp.com/1/3d-printer-filament-types-3d-printing-3d-filament/

  • MatterHackers Filament Compare — https://www.matterhackers.com/3d-printer-filament-compare

  • Prusa Research Materials Guide — https://help.prusa3d.com/materials

Supplemental Resources

  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake
  • OpenSCAD User Manual — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Reference Appendices

All supporting documents for Lesson 5 are included below. You do not need to open any additional files.


Appendix A: Safety Checklist for 3D Printing

Complete this checklist before and after each printing session. Print it out and keep a copy at your printer station.


Pre-Print Setup

Work Area

  • Desk or table cleared of unnecessary items
  • Tripping hazards removed from around the printer
  • Adequate ventilation confirmed (window open, fan running, or fume enclosure active)
  • Class ABC fire extinguisher within arm’s reach
  • Smoke detector mounted above printer is functional

Printer Inspection

  • Nozzle is clean — no old filament residue baked on
  • Build plate is level (re-level if the printer has been moved or bumped)
  • Heated bed temperature sensor is attached and secure
  • All cables are secure and none are frayed or cracked — especially the flexible bed cable bundle
  • Thermal runaway protection is enabled (check firmware settings if unsure)

Filament Preparation

  • Filament spool rotates freely on the holder — no binding or tangling
  • Filament path is clear of obstructions from spool to extruder
  • Extruder drive gear is clean — not clogged with ground plastic
  • Filament is correctly loaded and primed (a few mm of filament extruded before starting)

Environmental Conditions

  • Room temperature is adequate (18–25°C ideal — extreme cold slows bed heating; extreme heat can soften PLA)
  • No direct drafts from windows or air conditioning blowing on the printer (drafts cause warping and layer splitting)
  • Adequate lighting to clearly see the first layer as it prints

During Print

First Layer Monitoring (Do Not Leave)

  • Watch the first 2–3 layers without interruption
  • Bed adhesion is correct — filament sticks flat, not lifting at corners or curling
  • Nozzle temperature is stable at target value
  • No unusual sounds (grinding, clicking, popping)

Regular Checks (Every 15–30 Minutes)

  • Print is building correctly — no layer shifting, no spaghetti
  • Filament is feeding smoothly from the spool
  • No grinding or skipping sounds from the extruder
  • No warping visible at part edges

Temperature Stability

  • Heated bed maintains consistent temperature throughout
  • Nozzle temperature does not fluctuate more than ±5°C
  • No thermal runaway warnings on the printer display

Stop the Print Immediately If

  • The nozzle jams or extrudes unevenly
  • Filament stops feeding entirely
  • Any burning smell is detected
  • Visible layer shifting occurs
  • Grinding or skipping sounds from the extruder
  • Any unusual chemical or burning odor
  • Smoke appears — cut power immediately

Post-Print

Cool Down

  • Allow the heated bed to cool naturally for 10–15 minutes before attempting print removal
  • Keep hands clear of the nozzle until it reads below 50°C
  • Confirm the printer is idle and all temperatures are dropping before touching

Print Removal

  • Use a proper spatula or scraper — not fingers or improvised tools
  • Remove the print only when the bed has fully cooled (PLA releases easily from PEI beds when cool)
  • Inspect the print for sharp edges, support stubs, or layer delamination
  • Sand or file sharp edges if the part will be handled

Equipment Cleaning

  • Wipe the nozzle with a brass wire brush when cooled to 50°C (never cold — residue must be slightly soft)
  • Remove any plastic debris and failed print material from the build plate
  • Check the extruder for embedded filament residue
  • Clear any visible dust from the electronics area

Workspace Cleanup

  • Return all tools to their proper storage location
  • Dispose of support material and failed prints in a bin (not on the floor)
  • Store filament in a sealed bag with desiccant
  • Confirm the workspace is clear and safe for the next user

Hazard Reference Summary

HazardTemperature / ConditionResponse
Hot nozzle190–260°CDo not touch; wait for < 50°C
Hot bed50–110°CDo not touch; allow full cool-down
Fumes (ABS/PETG)At operating tempVentilate; use enclosure with filtration
Electrical (power supply)120V / 240V mainsNever open while plugged in
Tangled filamentAnyClear before printing; never force-pull

Emergency Actions

  • Fire: Unplug immediately. Use a dry chemical (Class ABC) extinguisher — NOT water on electrical fires. Evacuate and call emergency services.
  • Burns: Rinse with cool (not cold) running water for 15+ minutes. Seek medical attention for any burn larger than a coin.
  • Fume inhalation: Move to fresh air immediately. Seek medical attention if symptoms (headache, dizziness, nausea) persist.

Last Reviewed: __________ Reviewed By: __________


Appendix B: Filament Comparison Table

Quick reference for choosing the right filament. All temperature values are typical ranges — always check the label on your specific spool. The spool always wins over this table.


Side-by-Side Comparison

PropertyPLAPETGTPU (Flex)ABS
DifficultyEasiestModerateHardVery Hard
Nozzle temp190–220°C230–250°C220–240°C230–250°C
Bed temp50–60°C70–85°C30–60°C90–110°C
Enclosure needed?NoNoNoYes
RigidityHighMediumNone — flexibleHigh
Impact resistanceLow (brittle)MediumVery highMedium
Heat resistanceLow (~60°C)Medium (~80°C)MediumHigh (~100°C)
FlexibilityNoneSlightRubber-likeNone
Moisture sensitivityLowMediumHighMedium
Fume concernLowestLowModerateHigh
Bed adhesionEasyUse glue stick on PEIEasyRequires enclosure + glue
Print speedNormalNormalSlow (20–30 mm/s)Normal
Stringing tendencyLowMedium–HighHighLow
Approximate cost$15–25/kg$15–30/kg$20–40/kg$15–25/kg
Recommended for beginners?✅ YesAfter PLAAfter experience❌ No

When to Use Each Material

PLA — Use for:

  • Prototypes and test prints
  • Classroom projects
  • Decorative objects and tactile models
  • Anything that won’t be exposed to heat, moisture, or heavy mechanical stress

PLA — Avoid for:

  • Objects left in a hot car or direct sun (softens above ~60°C)
  • Parts that need to flex or bend without cracking
  • High-impact applications

PETG — Use for:

  • Functional parts that need to be tougher than PLA
  • Parts exposed to mild heat or moisture
  • Mechanical components: brackets, clips, mounts
  • Food-contact applications (check your specific brand for food-safe certification)

PETG — Avoid for:

  • Very fine surface detail (it strings more than PLA)
  • Projects where you need the easiest possible first-time print

TPU / Flexible — Use for:

  • Wearable objects (wristbands, phone cases, watch straps)
  • Bumpers and shock absorbers
  • Grips and handles
  • Objects that must deform under pressure and return to shape

TPU — Avoid for:

  • Fine surface detail
  • Printers with Bowden extruders (the flexible filament buckles in the tube — direct drive only)
  • Your first few prints while still learning

ABS — Use for:

  • High-heat environments (car interiors, near motors)
  • Parts requiring post-processing (ABS sands, bonds with acetone vapor, and paints easily)
  • Professional or industrial contexts with proper dedicated ventilation

ABS — Avoid for:

  • Any classroom without a dedicated sealed fume enclosure and active filtration
  • Beginners
  • Any print where warping at the edges would be a problem and you have no enclosure

Slicer Profile Quick Reference

FilamentPrusaSlicer ProfileKey Changes from PLA Default
PLAGeneric PLABaseline — no changes needed
PETGGeneric PETGHigher temps; slower cooling; glue stick on PEI bed
TPUGeneric FlexReduce speed to 20–30 mm/s; reduce retraction
ABSGeneric ABSHigher temps; disable cooling fan; use enclosure

Filament Storage

All filament absorbs moisture from the air over time. Wet filament causes: popping or crackling sounds during printing, bubbles in extruded plastic, excessive stringing, and weak or brittle finished parts.

FilamentMoisture SensitivityStorage Recommendation
PLALowSealed bag with desiccant when not in use
PETGMediumSealed bag with desiccant; dry before use if stored open for weeks
TPUHighAlways store sealed; dry in oven at 65°C for 4–6 hours if moisture-absorbed
ABSMediumSealed bag with desiccant

Sources: All3DP Filament Types Guide; MatterHackers Filament Compare; Prusa Research Materials Guide


Appendix C: Material Properties Quick Reference

Essential material data for FDM/FFF printing. Use alongside the Filament Comparison Table for material selection decisions.


Properties at a Glance

PropertyPLAPETGABSTPU
Nozzle temp (°C)200–220235–250240–260220–240
Bed temp (°C)20–6070–90100–11020–60
StrengthModerateHighVery HighLow (flexible)
FlexibilityNoneSlightSlightHigh
Ease of printingVery EasyEasyHardModerate
Cost ($/kg)$15–25$20–30$18–28$30–50
Print speed40–60 mm/s30–50 mm/s20–40 mm/s10–30 mm/s
Bed adhesionEasyModerateRequires prepEasy
UV resistanceLowModerateHighLow
Chemical resistanceNoModerateYesNo

Heat Resistance After Printing

This is one of the most common reasons to choose a material other than PLA.

MaterialSafe to use up toSoftens atNotes
PLA~50–60°C~60–70°CNot suitable for car interiors or items near heat sources
PETG~80–100°C~100–110°CHandles warm environments well
ABS~90–110°C~110–120°CGood heat resistance; most demanding to print
TPU~60–80°C~80–100°CLimited heat resistance despite flex durability

Chemical Resistance

MaterialWaterAlcoholAcetoneOilsAcids
PLALowLowDissolvesLowLow
PETGHighModerateModerateHighModerate
ABSHighModerateDissolvesHighModerate
TPUModerateLowLowModerateLow

Acetone note: Can be used to smooth ABS surfaces (vapor or liquid application). Also dissolves PLA — keep acetone away from PLA prints and filament spools.


Strength After Printing — Curing Time

Freshly printed parts are not at full strength.

Time After PrintingApproximate Strength
0–24 hours70–80% of final strength
24–48 hours90–95% of final strength
48–72 hours~99% of final strength
7+ daysMaximum strength

Do not stress-test functional parts immediately after printing. Allow at least 24 hours before load testing.


Storage Conditions

FactorRecommended Range
Storage temperature15–25°C
Relative humidity30–50%
Light exposureAway from direct sunlight
ContainerSealed with desiccant packets

Quick Material Selection Guide

QuestionAnswer
First time printing?PLA
Need durability?PETG or ABS
Need flexibility?TPU
Need high strength?ABS or PETG
Quick test / prototype?PLA
Outdoor use?PETG or ABS
Food contact?Food-grade certified PETG (verify brand)
Heat resistant?ABS
Easiest possible print?PLA

Appendix D: Printer Maintenance Log

Copy this log and keep a printed or digital copy with your printer. Fill in the Printer Information section first, then log every maintenance event and issue as it occurs. A complete log is your best diagnostic tool when problems arise.


Printer Information

FieldValue
Printer model
Serial number
Purchase date
Firmware version
Last service date
Warranty expiry
Manufacturer support contact

Maintenance Schedule

Before each use (Daily)

  • Visual inspection — no visible damage, cables intact
  • Clean nozzle tip if residue is present
  • Verify build plate is level (re-level if printer was moved)
  • Confirm filament spool rotates freely with no tangles

Weekly

  • Clean extruder drive gear (compressed air or brush out ground plastic)
  • Inspect and wipe Z-axis rails and lead screw
  • Check all cable connections at the control board
  • Test emergency stop / power cut

Monthly

  • Full build plate leveling procedure (manual or automatic)
  • Clean interior of print chamber
  • Inspect heating elements and thermistor connections
  • Run a temperature calibration test print

Quarterly (every 3 months)

  • Replace nozzle if inner bore shows wear or repeat clogging
  • Full mechanical inspection — belt tension, eccentric nuts, frame screws
  • Check firmware for updates
  • Run a full calibration test print and document results

Maintenance Log

DateTypeDescriptionTime SpentIssues FoundResolutionBy

Types: Routine / Repair / Calibration / Cleaning / Part replacement


Issue Tracking Log

DateSymptomDiagnosisAction TakenStatusNotes

Statuses: Open / In progress / Resolved / Monitoring


Parts Replacement Record

DatePart ReplacedReasonSupplierCostNotes

Filament Compatibility Notes

Record your tested settings for each material on this specific printer. Published temperature ranges are starting points — your printer may run hotter or cooler than its display indicates.

FilamentBrandNozzle TempBed TempSpeedSuccess RateNotes
PLA
PETG
ABS
TPU
Other

Troubleshooting Quick Reference

Nozzle Clog

  • First response: Cold pull (heat to printing temp, push filament through manually, cool to 90°C, pull sharply)
  • Second response: Acupuncture needle or nozzle cleaning filament
  • Last resort: Replace nozzle

Bed Adhesion Problems

  • Check: Bed level, nozzle height from bed, bed surface condition (clean? worn?)
  • Fix by material: PLA → clean PEI with IPA; PETG → apply glue stick; ABS → glue stick + enclosure

Layer Shifting

  • Common causes: Belt too loose, motor current too low, print speed too high, X/Y axis obstruction
  • Check belt tension first — it’s the most common cause

Extrusion Issues (Under-extrusion)

  • Common causes: Partial clog, worn drive gear, incorrect extruder steps/mm, wet filament
  • Run a flow rate test: extrude 100 mm and measure actual output

Monthly Performance Summary

MonthPrint Success RateCommon IssuesOverall Assessment

Last log entry: __________ Logged by: __________ -e


Lesson 6 — Practical 3dm Commands and Text Embossing

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

You’ve built solid 3D geometry, organized it into modules, learned to verify it rigorously, and understood the physical realities of printing it safely. Now we’re going to add two powerful new capabilities to your toolkit.

The first is text. Adding text to 3D parts is more useful than it might sound at first. Engineers put part numbers on manufactured components so they can be identified after assembly. Makers label storage bins so they can find what they need. Designers emboss names and logos on products. Accessibility designers create braille labels. OpenSCAD’s text() function makes all of this parametric — you can generate a hundred labeled bins automatically, make the text content a parameter, and produce variants for different languages or quantities without touching the geometry code at all.

The second is the full 3dm command suite. You’ve been using 3dm build and 3dm info. There are three more commands — preview, orient, and slice — that round out the workflow from design to print.


Learning Objectives

By the end of this lesson you will be able to:

  • Use text() to add embossed and debossed labels to 3D models
  • Find available fonts on your system and write portable font code
  • Size text to fit a specific container using the cap-height model
  • Use the full 3dm command suite: build, info, preview, orient, slice
  • Use OpenSCAD string functions: str(), len(), search(), substr()
  • Apply let() for scoped variable declarations
  • Automate multi-variant text label generation in bash, PowerShell, and CMD

Concept 1: The Full 3dm Command Suite

Five Commands, One Workflow

You’ve been using two commands. Here’s the complete set:

CommandWhat It DoesOutput
3dm buildCompiles .scad source → .stl geometrybuild/main.stl
3dm infoReports dimensions and AI descriptionConsole text
3dm previewRenders model to an image filebuild/preview.png
3dm orientAI-suggested print orientationConsole text recommendation
3dm sliceCalls your slicer on the current STLG-code file
# BUILD VARIANTS
3dm build                          # standard build
3dm build --clean                  # delete build/ folder first, then rebuild
3dm build --watch                  # auto-rebuild when src/ files change

# INFORMATION AND DESCRIPTION
3dm info                           # bounding box, volume, triangle count, AI description
3dm info --file path/to/file.stl   # query a specific STL (not just the current build)
3dm info --view front              # generate description from the front view
3dm info --view top,front,isometric  # generate from multiple views

# ORIENTATION, PREVIEW, SLICING
3dm preview                        # render model to build/preview.png
3dm orient                         # AI recommendation for best print orientation
3dm slice                          # call slicer on build/main.stl

3dm orient — What It Does and How to Use It

3dm orient uses AI to analyze your model’s geometry and recommend which face should be placed down on the build plate for printing. This recommendation considers two things: minimizing the need for supports (overhangs), and maximizing the quality of visible surfaces (which sit better when they’re on the top or sides, not facing down toward the bed).

Use 3dm orient as a starting suggestion, but verify it with your own judgment. For complex parts, you may have competing priorities — perhaps the AI recommends an orientation that minimizes supports but puts a cosmetically important surface face-down against the bed, where it will look rough. Your own analysis matters.


Concept 2: Text on 3D Parts

Why 3D Text Is Useful

Before diving into syntax, it’s worth thinking about why you’d want text on a 3D print:

Identification — part numbers, serial numbers, batch codes. Manufacturing parts need to be traceable. A part with its number embossed on it can never be confused with another part.

Directional labels — “FRONT,” “TOP,” “THIS SIDE UP.” Assembly instructions encoded directly in the part.

Storage and organization — labels for bins, drawers, shelves. Parametric text means you can batch-generate 30 labeled bins automatically.

Personalization — names, logos, messages on gifts, art, and personal projects.

Accessibility — braille labels for visually impaired users. OpenSCAD can generate braille if you encode the dot patterns.


Step 1 — The text() Function

How Text Works in OpenSCAD

text() creates a 2D shape from a text string. By itself, it’s flat — it has no height. You add height by wrapping it in linear_extrude(), which pushes the 2D letterforms straight up along the Z axis.

Embossed text is raised above the surface — the letters stand up above the base. This is more visible and readable, especially at small sizes, because there’s contrast between the raised letters and the surrounding surface.

Debossed text (also called engraved or incised) is carved into the surface — the letters are sunken below the surrounding surface. This reads well when the sunken areas catch shadow, or when filled with paint. It also doesn’t add any height to the overall part dimensions.

// Full text() parameter reference
linear_extrude(height=1.5)
  text(
    text      = "3dMake",           // the string to display
    size      = 10,                  // cap height in mm (capital letter height)
    font      = "Liberation Sans",   // font family name (more on this in Step 2)
    halign    = "center",            // horizontal alignment: "left", "center", "right"
    valign    = "baseline",          // vertical alignment: "top", "center", "baseline", "bottom"
    spacing   = 1.0,                 // letter spacing multiplier (1.0 = normal)
    direction = "ltr",               // text direction: "ltr" (left-to-right) or "rtl"
    language  = "en",
    script    = "latin"
  );

// EMBOSSED: raised letters sitting on top of the base
cube([80, 15, 5]);
translate([40, 7.5, 5])             // sit text on top face (Z=5)
  linear_extrude(height=1.5)        // letters are 1.5mm tall
    text("FRONT", size=6, font="Liberation Sans:style=Bold",
         halign="center", valign="center");

// DEBOSSED (ENGRAVED): letters carved into the surface
difference() {
  translate([0, 20, 0]) cube([80, 15, 5]);
  translate([40, 27.5, 5 - 0.8])   // start 0.8mm below the top face
    linear_extrude(height=1)        // 1mm cut: 0.8 into + 0.2 through (clean cut)
      text("BACK", size=6, font="Liberation Sans:style=Bold",
           halign="center", valign="center");
}

Understanding the debossed depth calculation: If the plate is 5 mm tall and you want 0.8 mm deep engraving, start the extrusion at z = 5 - 0.8 = 4.2. Extrude 1.0 mm (so it reaches z=5.2 — 0.2 mm past the top). This uses the 0.001 rule logic from Lesson 2: the cutter goes slightly beyond the face for a clean cut. The visible result is letters engraved 0.8 mm deep.


Step 2 — Finding and Using Fonts

Why Font Availability Is a Portability Problem

OpenSCAD uses fonts installed on your operating system. Different computers have different fonts. If you write code that uses “Arial” and another student or instructor tries to render it on a Linux machine that doesn’t have Arial, OpenSCAD will fall back to a substitute font — and the text proportions may change, potentially causing the text to overflow its container or look wrong.

The solution has two parts: check which fonts are available on your machine before writing your code, and define your font choice as a single parameter at the top of the file so it’s easy to change.

Finding Available Fonts

Linux (bash):

# List all available fonts
fc-list | sort | less

# Find fonts with "liberation" in the name
fc-list | grep -i "liberation"

# Get the exact format needed for OpenSCAD's font= parameter
fc-list --format="%{family}:style=%{style}\n" | grep -i liberation | sort | head -20
# Output examples:
# Liberation Sans:style=Bold
# Liberation Sans:style=Regular
# Liberation Mono:style=Bold

Windows (PowerShell):

# List all installed fonts
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
$fonts = (New-Object System.Drawing.Text.InstalledFontCollection).Families
$fonts | Select-Object Name | Sort-Object Name

# Search for a specific font
$fonts | Where-Object { $_.Name -like "*Arial*" } | Select-Object Name

On Windows, the most convenient method is the Help → Font List menu inside the OpenSCAD application — it shows every available font with its exact name string.

macOS (bash):

fc-list | sort
# or
system_profiler SPFontsDataType | grep "Full Name" | sort

Classroom-Safe Fonts (Available on Most Linux Systems)

These fonts are widely pre-installed and safe to use in code you’ll share with classmates:

  • Liberation Sans — clean, modern sans-serif, compatible proportionally with Arial
  • Liberation Mono — monospaced, excellent for part numbers and code
  • DejaVu Serif — serif font with good contrast for labels

Note

If OpenSCAD can’t find your specified font, it prints WARNING: No match for requested font family in the console. Font availability varies by OS — if text looks wrong, check the console for this warning and substitute an available font.


Step 3 — Font-Agnostic Code Pattern

Define Your Font Once

Instead of hardcoding a font name at every text call, define it once as a constant at the top of your file. This way, switching fonts is a one-line change, and the font choice is clearly documented.

// Define font choice once at the top — comment/uncomment for your OS
LABEL_FONT = "Liberation Sans:style=Bold";   // Linux
// LABEL_FONT = "DejaVu Sans:style=Bold";    // Linux alternative
// LABEL_FONT = "Arial:style=Bold";          // Windows / macOS
// LABEL_FONT = "Helvetica:style=Bold";      // macOS

module label(txt, size=8) {
  text(txt, font=LABEL_FONT, size=size, halign="center", valign="center");
}

module embossed_plate(message, plate_w=80, plate_d=15, plate_h=5,
                      text_size=8, relief=1.5) {
  cube([plate_w, plate_d, plate_h]);
  translate([plate_w/2, plate_d/2, plate_h])
    linear_extrude(height=relief)
      label(message, size=text_size);
}

embossed_plate("FRONT");
translate([0, 20, 0]) embossed_plate("BACK");
translate([0, 40, 0]) embossed_plate("LEFT");

Step 4 — Text Sizing: The Cap-Height Model

How the size Parameter Works

The size parameter in text() sets the cap height — the height of a capital letter in millimeters. This is not the total height of the text block; lowercase letters with descenders (g, p, q, y) extend further below the baseline.

Useful rules of thumb:

  • Total text block height ≈ size × 1.25 (to include descenders)
  • Width of a capital letter ≈ size × 0.65 to size × 0.75
  • Total width of an all-caps string ≈ size × 0.65 × character_count

These are approximations — the exact values depend on the specific font.

Auto-Fitting Text to a Container

When you need text to fill a specific width and height automatically, this module computes the right size:

module fitted_text(txt, container_w, container_h,
                   font="Liberation Sans:style=Bold") {
  char_count  = len(txt);
  size_by_w   = container_w / (char_count * 0.68);  // size that fills width
  size_by_h   = container_h * 0.75;                  // size that fills height
  fitted_size = min(size_by_w, size_by_h);            // use whichever is smaller

  echo(str("Fitted text size for '", txt, "': ", fitted_size, "mm"));

  text(txt, size=fitted_size, font=font,
       halign="center", valign="center");
}

// These labels auto-size to fit their containers
difference() {
  cube([60, 12, 5]);
  translate([30, 6, 5 - 0.8])
    linear_extrude(height=1)
      fitted_text("HELLO", 60, 12);
}

translate([0, 20, 0]) {
  cube([60, 12, 5]);
  translate([30, 6, 5])
    linear_extrude(height=1.5)
      fitted_text("WORLD", 60, 12);
}

Step 5 — String Functions

Building Labels Dynamically

The str() function converts any value to its string representation and concatenates multiple values into a single string. This is how you create part numbers, serial numbers, and version stamps programmatically.

// str() — convert values to strings and concatenate
part_id = str("PART-", 2026, "-", 42);
echo(part_id);   // PART-2026-42

// len() — length of a string or list
name = "OpenSCAD";
echo(len(name));   // 8

// search() — find the position of a character in a string
// Returns a list; [[4]] means found at index 4
echo(search("S", "OpenSCAD"));   // [[4]]

// substr() — extract a substring
// substr(string, start_index, length)
full = "BATCH-001";
batch  = substr(full, 0, 5);   // "BATCH"
number = substr(full, 6, 3);   // "001"
echo(batch, number);

Auto-Generating Serial Numbers

// Generate 5 parts with serial numbers SN-01 through SN-05
for (i = [1:5]) {
  serial = str("SN-", i < 10 ? "0" : "", i);   // zero-pad single digits
  translate([i * 35, 0, 0]) {
    cube([30, 12, 4]);
    translate([15, 6, 4])
      linear_extrude(1.5)
        text(serial, size=5, font="Liberation Sans:style=Bold",
             halign="center", valign="center");
  }
}

Step 6 — let() for Scoped Variables

What let() Does

In Lesson 3 you learned that OpenSCAD global variables are resolved at parse time, and that last-assignment wins. let() provides a way to declare variables that are scoped to a specific block — they only exist inside the let() block and don’t affect global scope.

let() is useful when you need intermediate calculated values in one place and don’t want them polluting the global namespace, or when you want to make a series of dependent calculations explicit within one block.

// let() scopes variables to the block they're declared in
let (
  base_w          = 80,
  base_d          = 50,
  plate_height    = 5,
  text_center_x   = base_w / 2,
  text_center_y   = base_d / 2
) {
  cube([base_w, base_d, plate_height]);
  translate([text_center_x, text_center_y, plate_height])
    linear_extrude(2)
      text("v1.0", size=6, halign="center", valign="center");
}
// text_center_x and text_center_y are not accessible outside the let() block

Step 7 — A Complete Parametric Label Plate

Here is a production-quality label module that uses every concept from this lesson:

// Parametric Label Plate
// Adjust these parameters and run: 3dm build
label_text   = "STORAGE BOX";
label_w      = 80;        // mm — plate width
label_h      = 18;        // mm — plate height
plate_depth  = 3;         // mm — plate thickness
text_depth   = 1.2;       // mm — engraving depth
font_size    = 7;         // mm — cap height of text
corner_r     = 2;         // mm — corner rounding radius

module label_plate(txt, w, h, t, td, fs, cr) {
  difference() {
    // Rounded rectangle base (minkowski creates rounded corners)
    minkowski() {
      cube([w - 2*cr, h - 2*cr, t], center=true);
      cylinder(r=cr, h=0.01, $fn=16);
    }
    // Engraved text, centered
    translate([0, 0, t/2 - td + 0.001])
      linear_extrude(td + 0.001)
        text(txt, size=fs, font="Liberation Sans:style=Bold",
             halign="center", valign="center", $fn=4);
    // Mounting hole for wall attachment
    translate([w/2 - 6, 0, -0.001])
      cylinder(r=1.5, h=t + 0.002, $fn=16);
  }
}

label_plate(label_text, label_w, label_h, plate_depth, text_depth, font_size, corner_r);

Step 8 — Automating Multi-Label Generation

Once your label design is parametric, you can generate a whole set of labels automatically — one build command per label variant.

Linux / macOS (bash):

#!/bin/bash
LABELS=("FRONT" "BACK" "LEFT" "RIGHT" "TOP" "BOTTOM")
mkdir -p build/labels

for label in "${LABELS[@]}"; do
  filename=$(echo "$label" | tr '[:upper:]' '[:lower:]')
  output="build/labels/${filename}.stl"
  echo "Generating: $label → $output"
  openscad -D "label_text=\"${label}\"" -o "$output" src/main.scad
  [ $? -eq 0 ] && echo "  OK" || echo "  FAILED"
done
echo "Done. Output: build/labels/"

Windows (PowerShell):

$labels = @("FRONT", "BACK", "LEFT", "RIGHT", "TOP", "BOTTOM")
New-Item -ItemType Directory -Force -Path "build\labels" | Out-Null

foreach ($label in $labels) {
  $filename = $label.ToLower()
  $output   = "build\labels\$filename.stl"
  Write-Host "Generating: $label → $output"
  openscad -D "label_text=`"$label`"" -o $output "src\main.scad"
  if ($LASTEXITCODE -eq 0) { Write-Host "  OK" } else { Write-Host "  FAILED" }
}
Write-Host "Done."

Windows (CMD):

@echo off
mkdir build\labels 2>nul
FOR %%L IN (FRONT BACK LEFT RIGHT TOP BOTTOM) DO (
  echo Generating: %%L
  openscad -D "label_text=\"%%L\"" -o "build\labels\%%L.stl" src\main.scad
  IF %ERRORLEVEL% EQU 0 (echo   OK) ELSE (echo   FAILED)
)
echo Done.

Exercises

Exercise 6.1: Find the fonts available on your computer using the appropriate command for your OS. List three font names in the exact format required by OpenSCAD’s font= parameter (e.g., Liberation Sans:style=Bold).

Exercise 6.2: Create a parametric name plate module where the text is auto-sized to fill 75% of the plate width. Test it with strings of 3, 6, 9, and 12 characters — verify that the text scales correctly and doesn’t overflow.

Exercise 6.3 (Advanced): Write a shell script that generates 10 identical parts with serial numbers SN-001 through SN-010 embossed on each. Display success or failure for each part and the total file count at the end.


Quiz — Lesson 6 (15 questions)

  1. What does 3dm orient output and when would you use it?
  2. What is the difference between embossed text and debossed (engraved) text in 3D printing? How does the OpenSCAD code differ?
  3. What does the size parameter in text() represent specifically? Is it the total height of the text block?
  4. What parameter in text() controls horizontal alignment, and what are the three main options?
  5. What does str("PART-", 2024, "-", 1) return?
  6. What does len("OpenSCAD") return?
  7. What is the purpose of let() in OpenSCAD, and how does it differ from declaring a global variable?
  8. What does setting $fn=4 do to letters rendered with text()?
  9. What does 3dm preview produce and where does the output file go?
  10. What is the format for specifying a font style (e.g., bold) in OpenSCAD’s font= parameter?
  11. Explain the depth calculation for debossed text: if a plate is 6 mm tall and you want 1 mm engraving depth, where do you position the linear_extrude() call and what height do you give it?
  12. What does substr("BATCH-001", 6, 3) return?
  13. What happens if you use text() without wrapping it in linear_extrude()?
  14. Why is defining the font as a constant at the top of your file (e.g., LABEL_FONT = "Liberation Sans:style=Bold") better than hardcoding it in every text() call?
  15. Write the OpenSCAD code to create a 50×20×4mm plate with the text “LOT-42” engraved 1.5mm deep, centered on the top face.

Extension Problems (15)

  1. Build a parametric serial number generator: accept a prefix string and a starting number, and generate a set of embossed labels with incrementing serial numbers.
  2. Create a dynamic version stamp: use str() to combine a product name, major version, and minor version, all as separate parameters.
  3. Design a 4-up label sheet: four identical labels in a 2×2 grid, using translate() and a for loop with two variables.
  4. Build a two-line label: stack two text() calls at different heights. Line 1 is the label text; line 2 is a smaller subtitle.
  5. Create a label with a decorative border: use difference() to cut a framing slot into the top face of the label plate.
  6. Use 3dm orient on three different models (a flat slab, a tall cylinder, an L-bracket) and document whether you agree with the AI suggestion in each case.
  7. Build a “batch tag” system: a module that generates 12 small tags in a row, each with a different serial number from a list.
  8. Design a keychain tag: a rounded rectangle with a ring hole, parametric text, and a border around the text.
  9. Use search() to find the position of a separator character (dash or underscore) in a part-number string. Explain a practical use case for this.
  10. Build a “negative space” text plate: a plate with all letters cut completely through, creating a stencil or silhouette effect.
  11. Design a parametric drawer label holder: a clip that attaches to the front edge of a drawer and holds a flat label insert.
  12. Create a font comparison plate: render the same text string using Liberation Sans, Liberation Mono, and DejaVu Serif side by side on one base plate.
  13. Write a screen-reader accessibility guide for the five 3dm commands. For each command: what it does, expected output, and how to interpret that output without visual reference.
  14. Write a module that auto-reduces font size to fit text within a fixed-width container. The module should reduce size in 0.5 mm steps until the estimated width fits.
  15. Design a production part-marking system: a jig that holds 10 small labels in a row, each with an incremented part number, ready to print all at once as one STL file.

References and Helpful Resources

  • 3DMake GitHub Repository — Command Reference — https://github.com/tdeck/3dmake

  • OpenSCAD User Manual — Text and Fonts — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Text

Supplemental Resources

  • Programming with OpenSCAD EPUB Textbook — assets/Programming_with_OpenSCAD.epub — String functions and text embossing examples
  • OpenSCAD Quick Reference — https://programmingwithopenscad.github.io/quick-reference.html — All string function syntax
  • CodeSolutions Repository — https://github.com/ProgrammingWithOpenSCAD/CodeSolutions — Worked text embossing examples
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Extension Project and Reference Appendices

All supporting documents for Lesson 6 are included below. You do not need to open any additional files.


Appendix A: Parametric Keychain — Extension Project

Estimated time: 2–4 hours

Overview

This extension project applies the text embossing and parametric design skills from Lesson 6 to build something immediately usable: a personalized keychain. The goal is not just to make one keychain — it’s to build a system that can produce any variant (different names, sizes, materials) by changing a small set of top-level variables. That’s what makes it a professional parametric design rather than a one-off model.

Learning Objectives

By completing this project, you will:

  • Create parametric OpenSCAD modules that accept user inputs as top-level variables
  • Implement embossed and debossed text using linear_extrude() of 2D text shapes
  • Generate and test multiple design variants systematically
  • Document design parameters for reproducibility and user customization

Objective

Create a keychain.scad file that adapts to custom text, dimensions, and attachment ring size — all through top-level parameter variables. Anyone with your .scad file should be able to produce a custom keychain by changing only the variables at the top of the file.

Tasks

  1. Create keychain.scad with these top-level parameters at minimum: name, tag_w, tag_h, tag_thickness, text_size, ring_d. Add others as your design requires. Every dimension in the file should trace back to one of these variables.

  2. Implement text using linear_extrude() of a 2D text() shape. Add either embossed text (the letters rise above the surface) or debossed text (the letters are engraved into the surface). Embossed text is more durable; debossed text is easier to read when painted or filled with ink.

  3. Produce three size variants — small (25 mm wide), medium (35 mm wide), large (45 mm wide) — by changing only tag_w and tag_h proportionally. Export an STL for each and record print time and filament weight.

  4. Test the key ring attachment by inserting a standard key ring (typically 25–30 mm diameter wire) through the attachment loop. Document what ring diameter fits, and whether the attachment point survives a reasonable tug test.

Deliverables

  • keychain.scad — fully parametric source file with all key dimensions as named variables and comments explaining each
  • Three STL variant files (small, medium, large)
  • Completed student documentation template (Appendix B of this document)
  • Print settings log and fit-test report for key ring attachment

Starter Code

Use the minimal keycap example as your starting structure for the shell + emboss pattern. The more advanced examples below show how to add circular text arrangements, multi-line compositions, and font variation.

Minimal Starting Point:

// Cube Keycap — Structural Reference
// This shows the shell + emboss pattern. Replace with keychain geometry.

keysize    = 18;    // mm — tag size
keyheight  = 12;    // mm — tag thickness
wall       = 1.2;   // mm — shell wall
letter     = "R";   // change to your text
lettersize = 10;    // mm — text size
letteraise = 0.8;   // mm — emboss height above surface

module shell() {
  difference() {
    cube([keysize, keysize, keyheight], center=false);
    translate([wall, wall, wall])
      cube([keysize - 2*wall, keysize - 2*wall, keyheight], center=false);
  }
}

module emboss() {
  translate([keysize/2, keysize/2, keyheight - 0.01])
    linear_extrude(height=letteraise)
      text(letter, size=lettersize, halign="center", valign="center");
}

union() {
  shell();
  emboss();
}

Parametric Keychain Nameplate — use this as your primary starting scaffold:

// Customizable Keychain Nameplate
// Change the parameters below to create your own variant.

// ---- Top-Level Parameters (change these) ----
name          = "ALEX";    // text to emboss on the tag
tag_w         = 35;        // mm — tag width
tag_h         = 20;        // mm — tag height (vertical dimension)
tag_thickness = 5;         // mm — tag thickness (Z height)
wall          = 1.2;       // mm — shell wall thickness
text_size     = 12;        // mm — font cap-height
text_raise    = 0.8;       // mm — emboss height above top face
ring_d        = 6;         // mm — key ring hole inner diameter
ring_wall     = 2;         // mm — wall thickness around ring hole

// ---- Derived Values ----
ring_outer_d  = ring_d + 2 * ring_wall;

// Verify ring attachment won't be too thin to print reliably
assert(ring_wall >= 1.2,
  str("ring_wall too thin to print reliably: ", ring_wall, "mm. Minimum: 1.2mm"));

// ---- Shell Module ----
module tag_shell() {
  difference() {
    cube([tag_w, tag_h, tag_thickness]);
    translate([wall, wall, wall])
      cube([tag_w - 2*wall, tag_h - 2*wall, tag_thickness]);  // open top — hollow shell
  }
}

// ---- Text Module ----
module tag_text() {
  translate([tag_w/2, tag_h/2, tag_thickness - 0.01])
    linear_extrude(height=text_raise)
      text(name,
           size=text_size,
           font="Liberation Sans:style=Bold",
           halign="center",
           valign="center",
           $fn=4);   // $fn=4 speeds up preview; use $fn=32 for final render
}

// ---- Key Ring Attachment Loop ----
// A short cylinder projecting from the top edge center with a hole through it.
module ring_attachment() {
  translate([tag_w/2, tag_h + ring_outer_d/2 - 0.001, tag_thickness/2])
    rotate([90, 0, 0])
      difference() {
        cylinder(d=ring_outer_d, h=tag_thickness, center=true, $fn=32);
        cylinder(d=ring_d,       h=tag_thickness + 0.002, center=true, $fn=32);
      }
}

// ---- Assembly ----
union() {
  tag_shell();
  tag_text();
  ring_attachment();
}

Advanced Technique: Circular Text Arrangement

// Arrange text in a circle around a center point.
// Useful for medallion-style keychains, badge designs, or decorative borders.

module rotate_text(display_text,
    text_size    = 10,
    distance     = 20,
    rotation_span = 360,
    tilt         = 0)
{
  rotate([0, 0, tilt])
  for (i = [0 : len(display_text) - 1]) {
    rotate([0, 0, -i * rotation_span / len(display_text)])
    translate([0, distance, 0])
      text(display_text[i],
           font="Liberation Sans:style=Bold",
           size=text_size,
           halign="center");
  }
}

// Usage: extrude the circular text arrangement
linear_extrude(height=2)
  rotate_text("MAKER", text_size=12, distance=30, rotation_span=75, tilt=30);

Advanced Technique: Multi-Line Text Composition

// Combine multiple text elements at different sizes for a professional nameplate.

module nameplate(name, role, plate_w=120, plate_d=60, plate_h=3) {
  union() {
    // Base plate
    cube([plate_w, plate_d, plate_h], center=true);

    // Main name — large, centered near top
    translate([0, 15, plate_h/2 + 1.5])
      linear_extrude(height=2)
        text(name, size=24, font="Liberation Sans:style=Bold",
             halign="center", valign="center");

    // Role — medium
    translate([0, 0, plate_h/2 + 1.5])
      linear_extrude(height=2)
        text(role, size=14, font="Liberation Sans:style=Regular",
             halign="center", valign="center");
  }
}

nameplate("Alex Chen", "3D Design Engineer");

Font Reference: Cross-Platform Options

The fonts below are widely available. Always fall back gracefully — define your font as a constant at the top of your file so you change it in one place.

// Define font as a constant — change here, applies everywhere
BODY_FONT  = "Liberation Sans:style=Bold";    // clean, reliable on all platforms
MONO_FONT  = "Liberation Mono:style=Regular"; // technical/code style
SERIF_FONT = "DejaVu Serif:style=Regular";    // classic, decorative

// Usage
linear_extrude(height=2)
  text("BOLD", size=20, font=BODY_FONT, halign="center");

Assessment Questions

  1. How did you use OpenSCAD parameters to enable customization without requiring users to edit code logic?
  2. What were the key differences in print time and material usage between your three size variants?
  3. How did you test the key ring attachment, and what adjustments did your testing reveal?

Appendix B: Parametric Keychain — Student Documentation Template

Author: ________________ Date: __________ Description: Design a fully parametric keychain that supports personalization and customization through top-level variables.


Design Concept

  • Keychain theme or purpose (personal use, gift, label system, other):
  • Design elements (shape, attachment method, text or symbol, any decorative features):
  • Parametric strategy — what will be variables, and what will be fixed geometry?

Parametric Variables

List every named variable in your file and what it controls.

VariableDefault ValueUnitPurpose / What it affects
mm
mm
mm
mm

Variant Configurations

Document the three variants you produced. Change only size-related variables between variants — text, attachment, and structural relationships should scale automatically.

Varianttag_w (mm)tag_h (mm)text_size (mm)Est. print timeEst. filament (g)
Small
Medium
Large

SettingValueNotes
Layer height
Infill
SupportsYes / No
Nozzle temperature°C
Bed temperature°C
Material

Key Ring Attachment Test

TestResult
Ring diameter testedmm
Did ring fit through attachment loop?Yes / No / Tight
Does the loop survive a firm tug?Yes / No
Wall thickness at attachment pointmm
Any deformation or cracking observed?

Adjustments needed based on testing:


For each variant, describe the print result:

Small variant:

  • Text legibility (clear / readable / hard to read):
  • Surface quality:
  • Any print issues:

Medium variant:

  • Text legibility:
  • Surface quality:
  • Any print issues:

Large variant:

  • Text legibility:
  • Surface quality:
  • Any print issues:

Customization Guide

Write this section for a future user who will download your .scad file and want to make their own version:

  1. To change the name: set name = "YOUR TEXT" at line ___.
  2. To change the size: adjust tag_w and tag_h proportionally. Recommended ratio: tag_h = tag_w * 0.57.
  3. To change the font: update the LABEL_FONT constant at line ___.
  4. Common customizations:
    • Smaller text that doesn’t overflow: reduce text_size until the preview looks right.
    • Different ring size: change ring_d to match your key ring’s wire diameter + 1 mm clearance.

Reflections

  1. Which parameterization decision had the most impact on the usefulness of the final design?

  2. How could someone who doesn’t know OpenSCAD still customize this design? What instructions would you write for them?

  3. What would you add in a future iteration — a second line of text, a logo, a different attachment style?


Attachments Checklist

  • .scad file with full parametric structure and comments on all variables
  • Photos of all three printed variants side by side
  • Photos of key ring fit test (ring inserted through attachment loop)
  • Completed variant configuration table
  • Customization guide written for a future user

Teacher Feedback

CategoryScore (0–3)Notes
Problem & Solution — keychains print and function; key ring fits
Design & Code Quality — fully parametric; all dimensions are variables; code is commented
Documentation — variant table complete; customization guide usable by a stranger
Total (0–9)

Appendix C: Parametric Keychain — Instructor Reference

Project Context

This extension project reinforces the core text embossing and parametric design content of Lesson 6. The key educational goal is parameter-driven design: every visible dimension should trace back to a named variable, so changing one number updates the entire design proportionally. Students who hardcode numbers (e.g., translate([35/2, 20/2, 5]) instead of translate([tag_w/2, tag_h/2, tag_thickness])) miss the point even if the print looks fine.

Key Learning Points to Reinforce

All dimensions must be variables. A fully parametric design produces a different variant for every combination of input values, without any code changes. If changing tag_w from 25 to 45 produces a broken design (text overflow, attachment loop detaches, walls become invalid), the design is not truly parametric.

The font constant pattern. Students should define LABEL_FONT = "Liberation Sans:style=Bold" at the top of the file and reference it in every text() call. This is a direct application of the DRY principle from Lesson 3. Hardcoding font strings in every text call is a common mistake.

Text overflow is a design failure, not a rendering quirk. OpenSCAD does not automatically fit text to a container — if text_size is too large, the text will extend beyond the tag boundary and produce an illegal geometry when combined with the shell. Students should either add an assert() that checks estimated text width, or test each variant in preview before exporting.

The key ring attachment geometry is the most technically demanding part. The cylinder that forms the attachment loop must: (1) be large enough for a real key ring wire to fit through, (2) have walls thick enough to print reliably (minimum ~1.2 mm), and (3) connect cleanly to the main tag body. The 0.001 mm overlap in the starter code’s translate() prevents non-manifold geometry at the junction.

Constraints (Enforce These)

  • All key dimensions (width, height, thickness, text size, ring diameter) must be named variables — no hardcoded numbers in geometry
  • At least three variants must be printed, not just rendered
  • Key ring attachment must be physically tested, not just visually inspected

Assessment Notes

Strong submissions show: text that scales proportionally with text_size as a variable, a ring attachment that has been tested with a real key ring, and a customization guide that actually tells a non-programmer how to make their own version.

Common weak areas: Text overflow not detected until printing (add assert() or preview check to starter code reminder), attachment loop too thin to be durable (check ring_wall >= 1.2 mm), and documentation that describes the final design but doesn’t guide future customization.

Extension opportunity: Students who finish early can investigate font rendering differences on their platform (Linux vs. macOS vs. Windows font availability), or add a second line of text (a subtitle or date) as a separate variable.


Appendix D: Slicing Settings Quick Reference

Use this reference when preparing your keychain (or any Lesson 6 design) for printing. Find your slicer and printer below. Recommended settings for most keychain prints: 0.20 mm layer height, 20% infill, no supports.


D1 — PrusaSlicer (Prusa Printers)

Use CaseLayer HeightInfillSupportsNotes
Quick test / prototype0.30 mm10%As neededDraft — fastest, roughest
Standard project0.20 mm15–20%As neededBest all-around starting point
Functional part0.20 mm30–40%As neededUse for parts under stress
Fine detail / display0.15 mm15%As neededSmoother surface; slower
Solid reference part0.20 mm40–50%RarelyRarely needed; long print

Filament Temperature Settings

FilamentNozzle TempBed TempNotes
PLA200–215°C50–60°CEasiest to print; default choice
PETG230–250°C70–85°CUse glue stick on PEI bed
TPU220–240°C30–60°CPrint at 20–30 mm/s max; direct drive only
ABS230–250°C90–110°CRequires enclosure; ventilate the room

Always check the temperature range printed on your filament spool — it varies by brand.

Support Settings Guide

Overhang AngleSupports Needed?Recommendation
< 45°NoNone
45–60°MaybePreview first; add if sagging
> 60°YesSupport on build plate only
Bridge < 20 mmNoBridges usually fine
Bridge > 20 mmMaybePreview; consider reorienting

Common Problems and Quick Fixes

ProblemLikely CauseFix
Print lifts off bedPoor adhesion / warpingAdd brim; use glue stick; re-level bed
Stringing between partsTemp too high / retractionLower temp 5°C; check retraction settings
Layer lines very visibleLayer height too thickUse 0.15 mm or 0.20 mm
Print takes too longLayer height too thin / infill too highUse 0.30 mm draft; reduce infill
Holes too smallFDM tolerance — always undersizedAdd 0.2–0.3 mm to hole diameter
Part broke at layer boundaryLoad perpendicular to layersReorient so load is parallel to layers
First layer not stickingBed not levelRun bed leveling routine
Spaghetti / print failureOverhang without supportsAdd supports or reorient

G-code Export Checklist

Before exporting, confirm:

  • Correct printer profile selected
  • Correct filament profile selected
  • Layer height appropriate for use case
  • Infill percentage set
  • Supports enabled if needed
  • Layer preview reviewed (no floating parts; supports where needed)
  • Print time and filament weight noted for your records

Sources: Prusa Research PrusaSlicer knowledge base (help.prusa3d.com); Hubs FDM guide (hubs.com)


D2 — Cura / Anycubic i3 Mega

Use CaseLayer HeightInfillSupportsNotes
Quick test / prototype0.30 mm10%As neededDraft — fastest, roughest
Standard project0.20 mm15–20%As neededBest all-around starting point
Functional part0.20 mm30–40%As neededUse for parts under stress
Fine detail / display0.15 mm15%As neededSmoother surface; slower
Solid reference part0.20 mm40–50%RarelyRarely needed; long print

Filament Temperature Settings

FilamentNozzle TempBed TempNotes
PLA200–210°C50–60°CEasiest to print; Anycubic default
PETG230–240°C70–80°CUse painter’s tape on steel bed
TPU220–235°C30–50°CReduce speed to 25–30 mm/s
ABS240–250°C100–110°CRequires ventilation; enclosed chamber recommended

Support Settings Guide

Overhang AngleSupports Needed?Recommendation
< 45°NoNone
45–60°MaybePreview first; add if sagging
> 60°YesTree supports (Cura) — easier to remove
Bridge < 20 mmNoBridges usually fine
Bridge > 20 mmMaybePreview; consider reorienting

Common Problems and Quick Fixes

ProblemLikely CauseFix
Print not adhering to steel bedPoor leveling / worn tapeRe-level; refresh painter’s tape
Filament oozing on travelTemperature too highLower temp 5°C; check Z-hop setting
Rough bottom layerBed too closeAdjust leveling knob
Holes too smallFDM tolerance — always undersizedAdd 0.2–0.3 mm to hole diameter
Part broke at layer boundaryLoad perpendicular to layersReorient so load is parallel to layers
Clogs at nozzleMoisture in filament / debrisDry filament; clear nozzle with needle
Spaghetti / complete failureBed not leveled or supports missedRe-level; add supports or reorient

G-code Export Checklist (Cura)

  • Anycubic i3 Mega printer profile selected
  • Correct filament type and diameter (1.75 mm)
  • Layer height set appropriately
  • Infill percentage set
  • Supports enabled if needed (tree supports preferred)
  • Nozzle and bed temperatures verified
  • Print preview checked (no floating parts)
  • Estimated time and filament weight noted

Sources: Anycubic official documentation (anycubic.com); Ultimaker Cura guide (ultimaker.com)


D3 — Bambu Studio / X1 Series

Use CaseLayer HeightInfillSupportsNotes
Quick test / prototype0.30 mm10%As neededDraft — use Standard mode
Standard project0.20 mm15–20%As neededBest all-around; Bambu default-optimized
Functional part0.20 mm30–40%As neededUse for load-bearing parts
Fine detail / display0.15 mm15%As neededBambu achieves excellent detail at speed
Solid reference part0.20 mm40–50%RarelyModern infill usually sufficient

Filament Temperature Settings

FilamentNozzle TempBed TempNotes
PLA (standard)200–210°C50–60°CFastest print times; Bambu-optimized profiles
PETG230–250°C70–80°CSlight cooling fan reduction for layer adhesion
TPU220–240°C20–30°CBest quality with Bambu’s tuned retraction
ABS240–260°C100–110°CRequires chamber heating; enclosed AMS recommended

Check Bambu’s material database for current profile updates — these are dynamically optimized.

Support Settings Guide

Overhang AngleSupports Needed?Recommendation
< 45°NoNone
45–60°MaybeAuto-supports may activate; accept defaults
> 60°YesBambu auto-tree supports; minimal removal effort
Bridge < 20 mmNoExcellent bridging on Bambu — no supports needed
Bridge > 20 mmMaybeOften bridgeable; preview before confirming

Common Problems and Quick Fixes

ProblemLikely CauseFix
Nozzle clogging mid-printThermal runaway / wet filamentDry filament in AMS; check nozzle temp
Layer splittingWrong material in AMS slotVerify correct material in Bambu Studio
Stringing / blobbingCooling fan too lowIncrease cooling; adjust material profile
Print lifts off bedBed leveling drift (rare on Bambu)Auto-calibrate via Bambu Studio
Holes undersizedFDM tolerance — always undersizedAdd 0.3–0.4 mm to hole diameter
Part broke at layer boundaryLoad perpendicular to layersReorient so load is parallel to layers
Print aborts unexpectedlyAMS issue / filament jamClear AMS; verify filament path
Multi-material print misalignedNozzle offset miscalibrationRun auto-calibration in maintenance menu

G-code Export Checklist (Bambu Studio)

  • Correct printer (X1 / X1E) and hotend selected
  • Filament material and color match actual AMS configuration
  • Layer height optimal for desired quality
  • Infill and supports set appropriately
  • Print preview shows correct color layering (if multi-material)
  • Estimated time and filament weight acceptable
  • Camera enabled for remote monitoring
  • Web upload or USB export ready

Sources: Bambu Lab documentation (bambulab.com); Bambu Lab Community forums (community.bambulab.com) -e


Lesson 7 — Parametric Transforms and the Phone Stand Project

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

You can now create shapes, combine them with CSG, organize them into modules, and add text. This lesson is about the next layer of precision: moving, rotating, mirroring, and scaling objects with mathematical exactness.

You’ve used translate() before to move shapes around. But there’s a subtlety about how OpenSCAD applies transforms — specifically, the order in which they execute — that is one of the most common sources of confusing bugs in OpenSCAD designs. Understanding the order rule deeply is one of the most valuable things you’ll get from this lesson.

This lesson also builds your first complete, multi-module project: a parametric phone stand. It’s not just an exercise — it’s a real, functional object. You’ll measure your actual phone, enter those measurements as parameters, and the math will generate the exact geometry needed to hold your phone at the angle you specify. Change the angle parameter and the entire stand recalculates.


Learning Objectives

By the end of this lesson you will be able to:

  • Apply translate(), rotate(), and scale() in the correct order for compound transforms
  • Use trigonometric functions (sin(), cos(), atan2()) to compute precise geometry positions
  • Use minkowski() to create rounded edges and mirror() to create perfectly symmetric parts
  • Build a complete parametric phone stand from three measured dimensions
  • Use $preview to conditionally speed up rendering during development
  • Apply vector math functions: norm(), cross(), and the dot product

Concept 1: Transform Order — The Most Important Rule in This Lesson

How OpenSCAD Applies Multiple Transforms

When you write multiple transforms on the same line, OpenSCAD applies them in right-to-left order — the transform closest to the geometry object applies first.

Read this line:

translate([10, 0, 0]) rotate([0, 0, 45]) cube(5);

Your eye reads left to right: “translate, then rotate.” But OpenSCAD executes right to left: first rotate (it’s closer to cube), then translate. So the cube is first rotated 45° around the origin, and then moved 10 mm in X.

Now read this:

rotate([0, 0, 45]) translate([10, 0, 0]) cube(5);

This time: first translate (cube moves 10 mm right), then rotate (the cube, now positioned at X=10, rotates around the origin). The result is that the cube ends up in a completely different location — it orbits around the origin rather than rotating in place.

Why This Matters

This rule has a real consequence: changing the order of transforms changes the position of your geometry, even if the transforms themselves are identical. This is the source of a lot of frustrating bugs in OpenSCAD designs, especially when the code looks correct to you.

The way to internalize it: think of it as nested functions. In translate(rotate(cube())), cube() runs first, then rotate() acts on its output, then translate() acts on that result. The same way f(g(x)) in math means “apply g first, then f.”

// Example A: cube rotates 45° in place, then moves 10mm right
// (rotate happens to the stationary cube, then translate moves it)
translate([10, 0, 0]) rotate([0, 0, 45]) cube(5);

// Example B: cube moves 10mm right first, then the rotated version orbits the origin
// (translate moves it first, then rotate spins it around origin — completely different result)
rotate([0, 0, 45]) translate([10, 0, 0]) cube(5);

Build both of these side by side. Look at where each cube ends up. The visual difference makes this rule concrete in a way that reading about it can’t.

The Rule in Plain Language

“The last transform written (closest to the shape) runs first.” Repeat this until it’s automatic.


Step 1 — Translate, Rotate, Scale

translate([x, y, z]) — Move

translate() moves its child object by the specified amount in each axis. translate([10, 0, 0]) moves 10 mm to the right. translate([0, 0, 5]) moves 5 mm up. Negative values move in the opposite direction.

You already know this one from previous lessons. The key reminder is the order rule above.

rotate([x_deg, y_deg, z_deg]) — Rotate

rotate() rotates its child around the X, Y, and/or Z axes by the specified angles in degrees. The rotation happens around the origin — if the object isn’t at the origin, it will orbit around it (which is sometimes what you want, sometimes not).

rotate([0, 0, 45]) rotates around the Z axis (spins in the XY plane). rotate([90, 0, 0]) rotates around the X axis (tips the object forward/backward). rotate([0, 90, 0]) rotates around the Y axis (tips the object left/right).

When you want to rotate an object around its own center (not the origin), translate it to the origin first, rotate it, then translate it to its final position:

// Rotate a cylinder around its own center, then position it
translate([20, 30, 0])        // 3. move to final position
  rotate([0, 90, 0])          // 2. rotate (runs before translate due to order rule)
    cylinder(h=20, r=5);      // 1. cylinder starts at origin

scale([x, y, z]) — Stretch or Compress

scale([1, 1, 2]) doubles the height of an object without changing its width or depth. scale([0.5, 0.5, 0.5]) shrinks everything by half. scale([1, 2, 1]) doubles depth only.

scale() is less common than the others because it changes proportions — a sphere becomes an ellipsoid, a cube becomes a rectangular box. But it’s useful for quick dimension experiments or for stretching a symmetrical part in one direction.

// Stretch a sphere 2x in Z to create an egg shape
scale([1, 1, 2]) sphere(r=10, $fn=32);

Step 2 — Trigonometry for Geometric Positioning

Why You Need Trig in Design

Trigonometry shows up in 3D design whenever you need to:

  • Place objects evenly around a circle
  • Compute an angle from a measured slope
  • Position something at a known distance and direction from a reference point
  • Calculate how deep a feature needs to be at a given angle

Fortunately, you don’t need to understand all of trigonometry deeply — you need three functions and one rule.

The rule: all angles in OpenSCAD are in degrees. Not radians. This is different from most programming languages. sin(90) in OpenSCAD returns 1 (correct for 90°). If you accidentally use radians, your numbers will be wildly off.

sin(), cos(), and Placing Things Around a Circle

sin(angle) and cos(angle) return the Y and X components of a unit vector pointing at that angle. Multiplying by a radius gives you the actual coordinates.

For a circle of radius r, the (x, y) position at angle a is:

  • x = cos(a) * r
  • y = sin(a) * r
// Place 6 cylinders evenly around a circle of radius 25mm
// 360° / 6 = 60° apart
for (i = [0:5]) {
  angle = i * 60;
  translate([cos(angle) * 25, sin(angle) * 25, 0])
    cylinder(r=3, h=5, $fn=16);
}

atan2(y, x) — The Safe Angle Calculator

When you need to go the other direction — from (x, y) coordinates back to an angle — use atan2(y, x).

atan(y/x) seems like it would work, but it fails in two quadrants. When x is negative (the left half of the circle), the division produces a value that places the angle in the wrong half of the circle. atan2(y, x) takes both components separately and always returns the correct angle for all four quadrants.

dx = -5;  dy = 5;
angle_correct = atan2(dy, dx);   // 135° — correct (upper-left quadrant)
angle_wrong   = atan(dy / dx);   // -45° — wrong (treats it as lower-right)
echo("atan2:", angle_correct, "  atan:", angle_wrong);

Always use atan2() when computing angles from coordinate pairs. Make this a habit.


Step 3 — minkowski() for Rounded Edges

What the Minkowski Sum Does

minkowski() computes something called the Minkowski sum of its children. The geometric meaning: it “rolls” the second shape over every point on the surface of the first shape, and the result is all the space swept out by this rolling.

In practice, the most useful application is rounding the edges and corners of a box. If you take the Minkowski sum of a cube and a small sphere, you get a box with perfectly rounded corners and edges — the rounding radius equals the sphere’s radius.

The variation used most often for printable parts is to use a cylinder instead of a sphere. A very flat cylinder (nearly zero height) rounds the vertical edges of a box but keeps the bottom face flat. This is ideal for parts that will sit on a surface, because a sphere-Minkowski box has a rounded bottom that makes it rock.

// Rounded box — sphere rounds all corners and edges including bottom
module rounded_cube(w, d, h, r=3) {
  minkowski() {
    cube([w - 2*r, d - 2*r, h - r], center=false);
    sphere(r=r, $fn=16);
  }
}

// Flat-base rounded box — cylinder rounds edges but keeps bottom flat
// The w/d dimensions shrink by 2r, and the height stays the same
module flat_rounded_cube(w, d, h, r=3) {
  minkowski() {
    cube([w - 2*r, d - 2*r, h], center=false);
    cylinder(r=r, h=0.01, $fn=24);   // nearly zero height: rounds edges, not top/bottom
  }
}

rounded_cube(40, 30, 20, r=4);
translate([50, 0, 0]) flat_rounded_cube(40, 30, 20, r=4);

Performance Warning

minkowski() is computationally expensive. With high $fn values on the secondary shape, it can take several minutes to compute. During development, keep the secondary shape at $fn=12–16. Only use $fn=32+ for final export. Even better: use the $preview technique in Step 5 to skip Minkowski entirely during quick iterations.


Step 4 — mirror() for Symmetry

Design One Half, Mirror the Other

Many designs have a line of symmetry — two legs, two wings, two ears, two cable clips. Instead of designing both halves separately (which introduces the risk of slight misalignment), design one half and mirror it. The mirrored copy is guaranteed to be exactly symmetric.

mirror([1, 0, 0]) reflects across the YZ plane — negates X coordinates. mirror([0, 1, 0]) reflects across the XZ plane — negates Y coordinates. mirror([0, 0, 1]) reflects across the XY plane — negates Z coordinates.

// Design one ear, mirror it to get a symmetric pair
module ear_peg() {
  translate([20, 0, 0]) cylinder(r=4, h=8, $fn=32);
}

ear_peg();                     // right ear
mirror([1, 0, 0]) ear_peg();  // left ear — exact mirror image

// Mirror works for complex modules too
module mounting_clip() {
  difference() {
    cube([15, 8, 10]);
    translate([7.5, -0.001, 2])
      cylinder(r=3, h=8.002, $fn=32);  // cable channel
  }
}

translate([0, 20, 0]) {
  mounting_clip();
  translate([15, 0, 0]) mirror([1, 0, 0]) mounting_clip();  // symmetric partner
}

Step 5 — Build the Complete Phone Stand

Why Build This

The phone stand is your first complete multi-module project. It’s functional, parametric, and applies trigonometry to solve a real design problem. More importantly, it’s something you’ll actually use — which is a good test of your own design work.

Measuring Your Phone

Before writing code, use a ruler or calipers to measure:

  • Phone width: the dimension across the face (X dimension in the cradle)
  • Phone thickness: how thick the phone is (determines cradle depth)
  • Preferred angle: how far you want the phone to lean back from vertical (65° from horizontal is a comfortable default for most people)

The Full Parametric Design

// ============================================================
// Parametric Phone Stand
// ============================================================
// Measure your phone and enter the three values below.
// All other dimensions are computed automatically.
//
// PARAMETERS TO CUSTOMIZE:
// - phone_w: width of your phone in mm
// - phone_d: thickness of your phone in mm
// - angle:   viewing angle from horizontal (60–80 degrees typically)
// ============================================================

phone_w = 75;   // mm — phone width (fits in cradle)
phone_d = 9;    // mm — phone thickness (sets cradle clearance)
angle   = 65;   // degrees — viewing angle from horizontal

// Internal dimensions — computed from the parameters above
lip_h       = 15;   // mm — depth of cradle lip
base_h      = 5;    // mm — base plate thickness
cradle_wall = 3;    // mm — wall thickness around phone
r_fillet    = 3;    // mm — rounded edge radius

// Trigonometry: compute base depth from the viewing angle
// The phone support must be at the correct lean angle
base_d = (phone_d + 10) / cos(90 - angle);

module flat_rounded_cube(w, d, h, r=3) {
  // Guard against degenerate dimensions after subtracting rounding radius
  assert(w > 2*r && d > 2*r, "Dimensions too small for the rounding radius");
  minkowski() {
    cube([w - 2*r, d - 2*r, h]);
    cylinder(r=r, h=0.01, $fn=24);
  }
}

module base_plate() {
  // Wide, flat base that anchors the stand
  flat_rounded_cube(phone_w + 20, base_d + 10, base_h, r_fillet);
}

module back_support() {
  // Angled wall that supports the back of the phone
  // rotate([angle-90, 0, 0]) tilts the wall to the viewing angle
  rotate([angle - 90, 0, 0])
    flat_rounded_cube(phone_w + 6, cradle_wall, 60, r_fillet);
}

module lip() {
  // Bottom ledge that the phone rests on
  rotate([angle - 90, 0, 0])
    translate([0, -lip_h, 0])
      flat_rounded_cube(phone_w + 6, lip_h + cradle_wall, cradle_wall, r_fillet);
}

// Final assembly: base + back support + lip
base_plate();
translate([0, 0, base_h]) {
  back_support();
  lip();
}

Understanding the Trigonometry

The rotation rotate([angle - 90, 0, 0]) deserves an explanation.

In OpenSCAD, a rotation of 0° around the X axis means the object is vertical (standing straight up). A rotation of -90° tips it flat forward (horizontal). When we want the back support to lean at angle degrees from horizontal, we need a rotation of angle - 90 degrees:

  • If angle = 90 (vertical phone): rotate([0, 0, 0]) — no rotation, support is vertical
  • If angle = 65 (typical lean): rotate([-25, 0, 0]) — leans 25° back
  • If angle = 45 (steeper lean): rotate([-45, 0, 0]) — leans 45° back

After building the stand, try changing angle from 45 to 80 in 5-degree steps and rebuild each time. Watch the support geometry recalculate automatically for every value.


Step 6 — Adaptive Quality with $preview

Fast During Development, High-Quality for Export

$preview is a special OpenSCAD variable that is automatically true during F5 preview (the fast OpenSCAD preview) and false during F6 full render and 3dm build. You can use it to conditionally use lower-quality (faster) settings during development and automatically switch to high quality for final export.

// Low $fn during preview for fast renders; high $fn for final build
$fn = $preview ? 16 : 64;

sphere(r=20);  // uses $fn=16 in preview, $fn=64 during 3dm build

This is especially valuable with minkowski(), which can be very slow at high $fn. During development, replace the Minkowski operation with a plain box placeholder:

module rounded_box_adaptive(w, d, h, r=4) {
  if ($preview) {
    // Fast placeholder during development
    color("orange", 0.6) cube([w, d, h]);
  } else {
    // Full, accurate Minkowski sum for final export
    minkowski() {
      cube([w - 2*r, d - 2*r, h - r]);
      sphere(r=r, $fn=12);
    }
  }
}

Concept 2: Vector Math Functions

Three Functions Worth Knowing

norm(v) — returns the length (magnitude) of a vector. norm([3, 4, 0]) = 5. This is the Euclidean distance from the origin to the point (3, 4, 0), and it follows from the Pythagorean theorem: √(3² + 4² + 0²) = 5.

Dot product (a * b) — returns a single number that measures how “aligned” two vectors are. If both vectors point in exactly the same direction, the dot product equals the product of their lengths. If they’re perpendicular, it equals 0. If they point in opposite directions, it’s negative. Useful for checking angles between directions.

cross(a, b) — returns a vector perpendicular to both input vectors. cross([1,0,0], [0,1,0]) returns [0,0,1] — the Z axis is perpendicular to both X and Y. Useful for computing surface normals or finding the axis of rotation between two vectors.

// norm: length of a vector
v = [3, 4, 0];
echo("Length:", norm(v));   // 5

// dot product: alignment measure
a = [1, 0, 0];   // X axis
b = [0.7, 0.7, 0];
echo("Dot product:", a * b);   // 0.7

// cross product: vector perpendicular to both
c = cross([1, 0, 0], [0, 1, 0]);
echo("Cross:", c);   // [0, 0, 1] — the Z axis

Quiz — Lesson 7 (15 questions)

  1. In OpenSCAD, do transforms apply left-to-right or right-to-left (which transform runs first)?
  2. What is the result of cos(0) and sin(90) in OpenSCAD (working in degrees)?
  3. What is the key advantage of atan2(y, x) over atan(y/x) for computing angles?
  4. What does minkowski() do geometrically? Describe it in plain language.
  5. What does mirror([1, 0, 0]) do? Which plane does it reflect across?
  6. What does scale([1, 1, 2]) do to a sphere?
  7. Write OpenSCAD code to place 8 cylinders evenly spaced around a circle of radius 30 mm.
  8. What does norm([3, 4, 0]) return, and how is this computed?
  9. True or False: translate([10,0,0]) rotate([0,0,45]) cube(5) rotates the cube first, then translates it.
  10. What does setting $preview to true mean in OpenSCAD, and when is it set automatically?
  11. Why does using minkowski() with cylinder(h=0.01) instead of sphere() produce a flat bottom surface?
  12. In the phone stand design, the back support uses rotate([angle - 90, 0, 0]). If angle = 70, what is the actual rotation applied? What does this mean physically?
  13. What does cross([1,0,0], [0,1,0]) return and what is the geometric meaning?
  14. Explain why designing one half of a symmetric part and using mirror() is better than designing both halves separately.
  15. A design requires placing 5 components at the vertices of a regular pentagon centered at the origin. Using cos() and sin(), what is the formula for the coordinates of each vertex, given a circumradius of 25 mm?

Extension Problems (15)

  1. Redesign your phone stand with a USB cable slot cut through the lip. Make the slot width and depth parameters.
  2. Add rubber foot pockets to the base plate: four small rectangular cutouts on the bottom face, positioned at the corners.
  3. Create a phone stand variant that holds the phone in landscape (horizontal) orientation. Document which parameters changed and why.
  4. Build a radially symmetric decoration: 12 identical fins evenly spaced around a central cylinder using for loop and rotate().
  5. Use atan2() to compute the angle of a ramp and use that angle with rotate() to align a small object precisely on the ramp surface.
  6. Design a phone stand for a large tablet (e.g., 180mm × 240mm). Update the parameters, rebuild, and verify the stand still holds at the correct angle.
  7. Build a “compound arm” — three rigid link segments connected end-to-end, each at a different angle. Display all three as an assembly with no gaps or overlaps.
  8. Create an ergonomic keyboard wrist rest using minkowski() with a cylinder for smooth, flat-base contouring.
  9. Build a visual transform order demo: two colored objects that differ only in the order of translate() and rotate(), placed side by side with labels.
  10. Redesign the phone stand as a wall-mount: replace the base plate with a flat back plate that has two M3 mounting holes.
  11. Build a mirror-symmetric earring holder: design one branch with pegs, then use mirror() to create the symmetric partner. Both branches should connect to a central hanging loop.
  12. Use norm() to calculate the space diagonal of a rectangular prism (distance from one corner to the opposite corner) and use that value as a dimension in the design.
  13. Research OpenSCAD’s multmatrix() function. Build a shear transformation example (slanting a box into a parallelogram-shaped prism) that can’t be achieved with standard transforms.
  14. Add snap-fit clips to the phone stand cradle: two small flexible fingers that slightly grip the phone. Dimension the fingers using snap-fit principles from Lesson 8.
  15. Design a dual phone stand: two cradles side by side at different angles, sharing a common base. Use a for loop and parametric spacing.

References and Helpful Resources

  • OpenSCAD User Manual — Transformations — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations

  • OpenSCAD User Manual — Mathematical Functions — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Mathematical_Functions

  • OpenSCAD User Manual — Minkowski and Hull — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Minkowski_and_Hull

Supplemental Resources


Lesson 8 — Advanced Parametric Design and Interlocking Features

Estimated Time: 90–120 minutes
Course: 3dMake Certification — High School Distance Learning Track


Before You Start

Every design you’ve built so far has been a single-piece print. This lesson moves to multi-part assemblies: designs where two or more printed pieces must physically fit together. This is where the gap between “looks right on screen” and “works in real life” becomes most critical.

The central concept of this lesson is tolerance: the intentional gap between mating parts that makes them fit together correctly. Too tight and the pieces won’t go together at all. Too loose and they wobble, rattle, or fall apart. The exact right amount of clearance depends on your specific printer, your specific filament, and your slicer settings — and the only reliable way to know it is to measure it.

This lesson gives you a systematic, professional approach: print a tolerance test coupon, measure the actual results, encode those measurements as named constants in your code, and build designs that work the first time instead of after three reprints.


Learning Objectives

By the end of this lesson you will be able to:

  • Explain why FDM-printed holes are always undersized and how to compensate
  • Design press-fit and slip-fit joints using printer-specific tolerance values
  • Print and use a tolerance test coupon to measure your printer’s actual clearances
  • Design snap-fit cantilever arms sized correctly for different materials
  • Design dovetail slide joints and stackable assemblies
  • Use threaded insert pockets for secure metal-to-plastic fastening
  • Apply true chamfer geometry
  • Apply tolerance values as named constants throughout a design

Concept 1: The Physics of FDM Tolerances

Why Printed Holes Are Always Too Small

This is one of the most important physical facts about FDM printing, and it surprises almost every beginner the first time they encounter it.

When an FDM printer extrudes a bead of filament, that bead spreads slightly as it deposits — it squishes outward from the center of the extrusion path. This happens at every wall, but the direction of the squishing is important:

  • On outer walls (the outside of a part), the extrusion squishes outward from the wall’s nominal surface. The part comes out slightly larger than designed.
  • On inner walls (the inside of a hole), the extrusion squishes inward — toward the center of the hole. The hole comes out smaller than designed.

The result: a hole designed to be 10 mm in diameter prints as approximately 9.6–9.8 mm. A peg designed to be 10 mm prints as approximately 9.8–10.0 mm. Two parts with a 10 mm nominal dimension will not fit together — the peg is too large for the hole.

This isn’t a flaw in your printer. It’s a fundamental consequence of how FDM extrusion works, and every designer working with FDM printing accounts for it.

What “Clearance” Means

Clearance is the intentional difference in size between a peg (or shaft, or tab) and its mating socket (or hole, or slot). You make the peg slightly smaller than the socket — the amount of this size difference is the clearance.

Different clearances produce different fits:

Fit TypeClearance (typical PLA, 0.4mm nozzle)Behavior
Press-fit (permanent)0.0 – 0.1 mmRequires force to assemble; doesn’t come apart easily
Slip-fit (removable)0.2 – 0.3 mmSlides smoothly; can be assembled and disassembled by hand
Loose/clearance fit0.4 – 0.5 mmSome play and wobble; appropriate for hinges and pivots

These are starting-point estimates. Your actual values will differ based on your printer and materials. That’s what the test coupon is for.


Step 1 — The Tolerance Test Coupon

The tolerance test coupon is a small, quick print that gives you empirical data about your specific printer’s actual clearances. Print it once with your standard material and settings. Test each peg-socket pair. Record the results. These numbers become the constants in your design files.

You’ll need to do this test if you:

  • Use a new printer you haven’t printed on before
  • Switch to a significantly different filament (e.g., from PLA to PETG)
  • Change your nozzle size
  • Change your slicer settings significantly (especially layer height)
// Tolerance Test Coupon
// Prints a row of pegs and a row of matching sockets at five clearance values.
// After printing: test each peg in each socket. Record which clearances give
// press-fit, slip-fit, and loose fit.

nominal        = 10;     // mm — nominal peg diameter
test_h         = 8;      // mm — peg height
plate_t        = 3;      // mm — socket plate thickness
socket_d_outer = nominal + 8;   // mm — outer diameter of socket annulus

clearances = [0.0, 0.1, 0.2, 0.3, 0.4];   // mm — the five clearances to test

module test_peg(clearance) {
  // Peg diameter = nominal - clearance
  color("SteelBlue")
    cylinder(d=nominal - clearance, h=test_h, $fn=32);
}

module test_socket() {
  // All sockets have the same nominal hole; pegs vary
  color("Coral")
  difference() {
    cylinder(d=socket_d_outer, h=plate_t, $fn=32);
    translate([0, 0, -0.001])
      cylinder(d=nominal, h=plate_t + 0.002, $fn=32);
  }
}

module clearance_label(clearance) {
  // Small label showing the clearance value
  translate([0, -(nominal/2 + 5), 0])
    linear_extrude(1)
      text(str(clearance, "mm"), size=2.5, font="Liberation Sans",
           halign="center", $fn=4);
}

// Row 1: Pegs — each has a different clearance reduction applied
for (i = [0 : len(clearances) - 1]) {
  translate([i * (socket_d_outer + 4), 0, 0]) {
    test_peg(clearances[i]);
    clearance_label(clearances[i]);
  }
}

// Row 2: Sockets — all have the same nominal hole
translate([0, -(socket_d_outer + 8), 0])
  for (i = [0 : len(clearances) - 1]) {
    translate([i * (socket_d_outer + 4), 0, 0])
      test_socket();
  }

How to Read the Results

After printing, test each peg in each socket. Record:

Fit TypeTest MethodWhat to Record
Press-fitTightest peg that enters socket with firm thumb pressureYour press clearance
Slip-fitLoosest peg that doesn’t rattle in the socket when shakenYour slip clearance
Bearing/pivotLoosest peg that rotates smoothly without visible wobbleSlip + 0.05–0.1 mm

These measured values replace the rough estimates in the table above. Record them in a note or file, and use them for every design from now on.


Step 2 — Encoding Tolerance as Named Constants

Never Hardcode Tolerance Values

Tolerance clearance values should appear in your design file exactly once — at the top, as named constants. When you measure different clearances (because you’re on a different printer, or using PETG instead of PLA), you change the constant in one place and the entire design updates.

// ============================================================
// TOLERANCE CONSTANTS — measured from your test coupon print
// Run the test coupon, measure, and update these values.
// ============================================================
PRESS_FIT_C = 0.2;    // mm — tightest peg that enters with thumb pressure
SLIP_FIT_C  = 0.3;    // mm — loosest peg that doesn't rattle
SNAP_C      = PRESS_FIT_C;   // snap-fits use press-fit clearance

// Use these constants throughout the file:
// hole_r = peg_r - SLIP_FIT_C    (for a slip-fit hole)
// hole_r = peg_r - PRESS_FIT_C   (for a press-fit hole)

This is exactly the same DRY principle from Lesson 3 applied to physical measurements. The constants are derived from reality (your test print); the geometry uses those constants; change one measurement and everything that depends on it updates automatically.


Step 3 — Snap-Fit Cantilever Arms

What a Snap-Fit Is

A snap-fit is a self-locking fastener made entirely from the printed plastic itself. A thin, flexible beam (the cantilever arm) deflects as the mating part pushes past it, then springs back to its original position, locking the parts together. Think of the plastic tab that holds a battery cover in place, or the clip that holds a phone case together.

Snap-fits are one of the most elegant features you can design. When they work well, they’re intuitive, require no separate hardware, and can be assembled and disassembled dozens of times without wearing out. When they’re designed wrong, they either crack (too stiff) or don’t hold (too flexible).

The Flexibility Rule

The key design parameter is the beam flexibility ratio: beam_thickness / beam_length. For PLA, this ratio must be 0.15 or less — meaning the beam’s thickness must be at most 15% of its length. A beam that’s too thick relative to its length won’t flex and will crack instead of deflecting.

Different materials allow different ratios because they have different stiffness (elastic modulus):

MaterialMaximum beam_t / beam_lWhy
PLA0.15Relatively stiff; snaps or cracks if over-flexed
PETG0.18Slightly more flexible than PLA
Nylon0.20Good flexibility and fatigue resistance
TPU0.25Very flexible; excellent for repeated flex
ABS0.12More brittle than PLA; needs shorter/thinner beams
module snap_arm(beam_l=20, beam_t=1.8, beam_w=8, hook_h=1.2, hook_angle=30,
                material="PLA") {

  // Maximum flexibility ratio by material
  max_ratio = (material == "TPU")  ? 0.25 :
              (material == "PETG") ? 0.18 :
              (material == "Nylon")? 0.20 :
              (material == "ABS")  ? 0.12 :
              0.15;  // default: PLA

  ratio = beam_t / beam_l;

  // Validate before any geometry is created
  assert(ratio <= max_ratio,
    str("snap_arm: beam_t/beam_l ratio (", ratio,
        ") exceeds maximum for ", material, " (", max_ratio,
        "). Reduce beam_t to ≤ ", floor(beam_l * max_ratio * 10) / 10, "mm."));

  union() {
    // The flexible beam itself
    cube([beam_w, beam_l, beam_t]);
    // The hook at the end of the beam that catches the mating part
    translate([0, beam_l, 0]) union() {
      rotate([0, -hook_angle, 0])
        cube([beam_w, 2, hook_h]);
      translate([0, 0, beam_t])
        cube([beam_w, 2, hook_h]);
    }
  }
}

// PLA snap arm — standard sizing
snap_arm(beam_l=20, beam_t=1.8, beam_w=8, hook_h=1.5, material="PLA");
// For a 20mm PLA beam: max thickness = 20 × 0.15 = 3.0mm. This design uses 1.8mm — safe.

// PETG snap arm — can be slightly thicker, more resilient
translate([15, 0, 0])
  snap_arm(beam_l=20, beam_t=2.2, beam_w=8, hook_h=1.5, material="PETG");

Orienting the Snap-Fit for Printing

Snap-fit beams need to flex in one specific direction. For maximum strength and flexibility, the beam should be printed so that the flex direction is perpendicular to the layer lines. This means orienting the print so the beam runs horizontally and flexes up-down (in the Z direction), not sideways (where layer interfaces would create a weakness).


Step 4 — Dovetail Slide Joint

What a Dovetail Is and Why It’s Useful

A dovetail joint has a trapezoidal cross-section — wider at one end than the other, like the tail of a dove. This shape means the joint can only slide in one direction. You can slide two dovetail pieces apart, but you cannot pull them perpendicular to the slide direction — the trapezoidal shape prevents it.

This makes dovetails excellent for: drawer rails, camera slider tracks, adjustable phone mounts, and any assembly where you want parts that can be separated easily but don’t fall apart during normal use.

dt_l     = 50;    // mm — length of the slide
dt_w_top = 8;     // mm — narrower dimension (top of trapezoid)
dt_w_bot = 12;    // mm — wider dimension (base of trapezoid)
dt_h     = 5;     // mm — depth of the dovetail profile
clearance = 0.2;  // mm — your measured slip-fit clearance

module dovetail_male(l=dt_l, w_top=dt_w_top, w_bot=dt_w_bot, h=dt_h) {
  // The trapezoidal profile, extruded along the Y axis
  profile = [
    [-w_bot/2, 0], [ w_bot/2, 0],   // wide base
    [ w_top/2, h], [-w_top/2, h]    // narrow top
  ];
  rotate([90, 0, 0])
    linear_extrude(l)
      polygon(profile);
}

module dovetail_female(l=dt_l, w_top=dt_w_top, w_bot=dt_w_bot, h=dt_h, c=clearance) {
  // Female slot: same shape but all dimensions enlarged by clearance
  profile = [
    [-(w_bot/2 + c), -0.001], [ w_bot/2 + c, -0.001],
    [ w_top/2 + c,   h + c ], [-(w_top/2 + c), h + c]
  ];
  rotate([90, 0, 0])
    linear_extrude(l + 0.002)
      polygon(profile);
}

// Part A: a plate with a female dovetail slot
difference() {
  cube([30, dt_l, 15]);
  translate([15, -0.001, 5])
    dovetail_female();
}

// Part B: the sliding piece with a male dovetail
translate([40, 0, 0]) {
  cube([30, dt_l, 10]);
  translate([55 - 40, 0, 5])
    dovetail_male();
}

Step 5 — Stackable Bin System

Designing Bins That Stack

For parts that stack vertically, one piece needs a raised lip on top that fits inside the walls of the next piece. The outer dimensions of this lip must be slightly smaller than the inner dimensions of the wall — by your slip-fit clearance — so the stacked bin sits snugly but can still be separated by hand.

bin_w     = 80;    // mm — bin width
bin_d     = 60;    // mm — bin depth
bin_h     = 40;    // mm — bin height
wall      = 2.5;   // mm — wall thickness
lip_h     = 5;     // mm — height of the stacking lip
lip_clear = 0.25;  // mm — your measured slip-fit clearance

module bin_body() {
  difference() {
    cube([bin_w, bin_d, bin_h]);
    translate([wall, wall, wall])
      cube([bin_w - 2*wall, bin_d - 2*wall, bin_h]);  // hollow interior, open top
  }
}

module stacking_lip() {
  // Lip outer dimensions = bin inner dimensions - clearance
  // This makes the lip fit inside the next bin's walls
  translate([lip_clear, lip_clear, bin_h])
    difference() {
      cube([bin_w - 2*lip_clear, bin_d - 2*lip_clear, lip_h]);
      translate([wall - lip_clear, wall - lip_clear, wall])
        cube([bin_w - 2*wall, bin_d - 2*wall, lip_h]);
    }
}

bin_body();
stacking_lip();

After building this, change lip_clear and note how it affects the stacking fit. If you print two bins and they don’t stack or are too loose, adjust lip_clear by 0.05–0.10 mm and reprint the test piece.


Step 6 — Heat-Set Threaded Inserts

The Problem with Plastic Threads

If you tap a thread directly into printed plastic and screw a bolt into it repeatedly, the plastic threads will wear down and eventually strip. This makes plastic-threaded holes unsuitable for any assembly that will be disassembled and reassembled multiple times.

Heat-set threaded inserts solve this problem. They are small brass cylinders with internal threads and external ridges. You heat them with a soldering iron and press them into a printed hole — the heat melts the plastic around the insert, the ridges embed into the material, and when it cools, you have a permanent metal thread that won’t strip even after many assembly cycles.

Heat-set inserts are commonly available in M2, M3, and M4 sizes and are standard hardware in professional product design.

// M3 brass heat-set insert dimensions:
// Outer diameter: ~4.5mm; Length: ~5.7mm
module m3_insert_pocket(depth=6) {
  // Slightly undersized hole — insert is heated and pressed in with force
  cylinder(r=2.35, h=depth + 0.001, $fn=16);  // (4.5 + 0.2) / 2
}

// M4 brass heat-set insert:
// Outer diameter: ~5.6mm
module m4_insert_pocket(depth=8) {
  cylinder(r=2.9, h=depth + 0.001, $fn=16);   // (5.6 + 0.2) / 2
}

// Example: a plate with two M3 insert pockets
difference() {
  cube([40, 30, 10]);
  translate([10, 15, -0.001]) m3_insert_pocket(depth=10.002);
  translate([30, 15, -0.001]) m3_insert_pocket(depth=10.002);
}

Note: Heat-set insert hole dimensions vary between manufacturers. Check the datasheet for your specific inserts. The values above are typical for common brass inserts.


Step 7 — True Chamfers

What a Chamfer Is

A chamfer is a 45° beveled edge where two surfaces meet at a sharp corner. Chamfers serve two purposes in printed parts: they look more professional than a sharp edge, and they can act as lead-ins that help parts align during assembly.

A common mistake is creating a chamfer by simply cropping the top of a part at an angle — this produces a slanted surface, but it’s not a true chamfer created from the model’s geometry. A true chamfer is created using a difference() boolean cut.

module chamfered_box(w, d, h, c=2) {
  // c = chamfer size in mm (both horizontal and vertical dimension of the bevel)
  difference() {
    cube([w, d, h]);
    // Remove the top c millimeters of the edges
    // by cutting a hollow frame shape from the top
    translate([0, 0, h - c])
      difference() {
        cube([w, d, c + 0.001]);                      // top layer of the box
        translate([c, c, 0]) cube([w - 2*c, d - 2*c, c + 0.001]);  // inset rectangle
      }
  }
}

chamfered_box(50, 40, 20, c=3);

The chamfer logic: take the top c mm of the box as a separate region. Subtract an inset rectangle from it, leaving only the border frame. Remove that border frame from the original box. The result is a clean 45° bevel around the top perimeter.


Step 8 — Dowel Pins for Alignment

Why Alignment Pins Matter

When two parts are assembled by hand, they may not align perfectly — especially if the mating surfaces are flat. Dowel pins are small cylindrical protrusions on one part that fit into matching pockets on the other. They guarantee precise alignment regardless of how the parts were held during assembly.

One part has the pins (protruding pegs). The other has the pockets (matching blind holes). The pins enter the pockets with a press-fit or slip-fit clearance, locking the parts into perfect alignment.

pin_r     = 3;      // mm — pin radius
pin_h     = 6;      // mm — pin height
pin_clear = 0.15;   // mm — slightly tighter than slip-fit for precise alignment

module alignment_pin() {
  cylinder(r=pin_r, h=pin_h, $fn=32);
}

module alignment_pocket() {
  // Slightly larger radius and slightly deeper — ensures pin seats fully
  cylinder(r=pin_r + pin_clear, h=pin_h + 0.5, $fn=32);
}

// Part A — has two alignment pins protruding from top face
cube([50, 40, 5]);
translate([10, 10, 5]) alignment_pin();
translate([40, 30, 5]) alignment_pin();

// Part B — has matching pockets in bottom face
translate([60, 0, 0])
  difference() {
    cube([50, 40, 5]);
    translate([10, 10, -0.001]) alignment_pocket();
    translate([40, 30, -0.001]) alignment_pocket();
  }

Exercises

Exercise 8.1: Print the tolerance test coupon. Test each peg-socket pair. Record your press-fit and slip-fit clearance values. Update PRESS_FIT_C and SLIP_FIT_C with your measured values.

Exercise 8.2: Design a snap-fit battery cover for a 60 × 40 × 20 mm space using your measured press-fit clearance and the snap_arm() module. Verify the beam flexibility ratio before printing.

Exercise 8.3 (Advanced): Create a parametric box set where a size_scale parameter (values 0.5, 1.0, 2.0) generates small, medium, and large boxes that all use the same lid design and tolerance values. Generate all three sizes with a bash/PowerShell loop and verify each with 3dm info.


Quiz — Lesson 8 (15 questions)

  1. Why do FDM-printed holes consistently come out smaller than designed? Explain the physical mechanism.
  2. What clearance range (in mm) produces a slip-fit for a typical FDM printer with a 0.4mm nozzle and PLA?
  3. What is a press-fit, and what application would you use one for?
  4. What is the beam_t / beam_l flexibility rule for PLA snap-fit cantilever beams?
  5. Why must you print a tolerance test coupon rather than using published clearance values from a chart?
  6. What is a heat-set threaded insert and why is it preferred over a plastic-tapped hole for assemblies that are disassembled repeatedly?
  7. What is a dovetail joint and in which direction does it lock?
  8. What does a stacking lip do in a stackable bin design, and how does clearance factor into its dimensions?
  9. True or False: a thicker snap-fit beam is easier to deflect than a thinner one of the same length.
  10. What happens if you design a stacking lip with clearance = 0mm?
  11. Explain the concept of “tolerance stack-up.” If three parts each have ±0.2mm dimensional variation, what is the worst-case total gap variation in an assembled chain of three?
  12. Why should tolerance clearance values be defined as named constants at the top of a file rather than hardcoded at each use?
  13. Describe how a chamfer is created using difference(). What shape is subtracted from the original?
  14. For a snap-fit clip made of PLA with beam_l = 18mm, what is the maximum beam_t allowed by the flexibility rule? Show your calculation.
  15. Describe how you would design and conduct a complete tolerance test for a new printer. What prints would you make, what would you measure, and how would you decide on your final clearance values?

Extension Problems (15)

  1. Design a complete stackable bin set (small, medium, large) where each size nests inside the next. Use your measured tolerance values throughout.
  2. Build a snap-fit box lid that attaches with four clips. Make the number of clips a parameter and validate the beam dimensions with assert().
  3. Design a press-fit peg and socket set with five clearances from 0.0 to 0.4 mm. Print one set, test all pairs, and create a table showing which clearance produced which fit type on your printer.
  4. Create a wall-mount organizer using snap-fit clips that attach to a standard pegboard (hole pitch = 25.4mm, hole diameter = 6.35mm).
  5. Build a two-part enclosure with heat-set insert pockets for M3 screws and matching through-holes for the bolts. Test with real hardware.
  6. Design a snap-together dice tray: the tray snaps into a carrying case lid using four snap clips.
  7. Create an alignment jig using two dowel pins and matching pockets. Use it to verify your printer’s positional accuracy by measuring pin spacing with calipers.
  8. Build a cable management clip with a snap-fit that can be opened and closed repeatedly for easy cable insertion and removal.
  9. Design a telescoping tube: an inner cylinder that slides freely inside an outer cylinder using your measured slip-fit clearance.
  10. Create a bayonet mount: a part that locks with a 90° twist.
  11. Design a “living hinge” — a thin flexible connection between two rigid sections that can be folded. Research the appropriate wall thickness and document which materials are suitable.
  12. Build a parametric drawer divider system: interlocking slotted panels that can be arranged in any grid configuration.
  13. Design a self-locking dovetail joint that slides together in one direction and resists being pulled apart in any perpendicular direction.
  14. Create a complete assembly drawing in OpenSCAD: an exploded view with each component translated away from the assembly center, with clear labels and a tolerance reference table as a comment block.
  15. Conduct a failure mode analysis for a snap-fit clip: list five ways it could fail in use, rate each by likelihood and severity, and propose a design modification to reduce the top two risks.

References and Helpful Resources

  • Snap-Fit Design Principles — Bayer MaterialScience Snap-Fit Design Manual

  • OpenSCAD User Manual — Difference and Boolean Operations — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/CSG_Modelling

  • Tolerance and Fit in FDM Printing — All3DP Guide — https://all3dp.com/2/fdm-3d-printing-tolerances/

Supplemental Resources

  • Programming with OpenSCAD EPUB Textbook — assets/Programming_with_OpenSCAD.epub — Assemblies and interlocking features
  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Extension Project and Reference Appendices

All supporting documents for Lesson 8 are included below. You do not need to open any additional files.


Appendix A: Snap-Fit Clip — Extension Project

Estimated time: 3–6 hours

Overview

This extension project takes the snap-fit concepts from Lesson 8 and turns them into a systematic engineering investigation. Rather than building a snap-fit and hoping it works, you will design a parametric test structure, print it at three different tolerance values, measure what happens, and let the data drive your final design.

This is how snap-fit components are actually designed in professional practice: tolerance ranges are established empirically for a specific material-printer combination, then codified as constants for future designs.

Learning Objectives

By completing this project, you will:

  • Design flexible components that must bend without failing
  • Conduct tolerance and material testing systematically
  • Understand the relationship between geometry, material properties, and functional performance
  • Document design iterations and trade-offs in a format that would transfer to a colleague

Objective

Design a parametric snap-fit clip with adjustable clip thickness and spacing. Use it to determine optimal tolerances for your specific printer and material combination.

Tasks

  1. Design a parametric snap-fit test piece with adjustable clip thickness and spacing. All key dimensions must be variables. The design must include at least one cantilever beam using the beam_t / beam_l flexibility rule from Lesson 8.

  2. Print test pieces for three tolerance values. For each variant, change only the tolerance variable — keep all other parameters fixed. Label each print (embossed text, or a note taped to the print).

  3. Test each clip for snap-fit behavior. For each variant: assemble and disassemble at least 5 times. Record the effort required, any deformation observed, and whether the clip still functions after 5 cycles.

  4. Refine dimensions based on results. Choose the tolerance value that produced the most reliable behavior and create a final clip design. Write a one-paragraph justification of your choice.

Deliverables

  • Source .scad file with parametric clip modules (all key dimensions as named variables)
  • Test print results table (see student documentation template in Appendix B)
  • Final clip design with recommended print settings documented
  • Completed student documentation template

Starter Code

The stackable bins example from Lesson 8 demonstrates the stacking rim and clearance pattern that snap-fit features build on. Use it as a reference for parametric structure, then design your own snap-fit geometry.

// Stackable Storage Bins — Structural Reference
// This example shows the clearance and rim pattern.
// Your snap-fit clip will use similar parametric constants.

bin_w        = 80;    // mm — bin width
bin_d        = 120;   // mm — bin depth
bin_h        = 60;    // mm — bin height
wall         = 2;     // mm — wall thickness
rim          = 3;     // mm — interlock rim height
chamfer      = 2;     // mm — top edge chamfer
stack_clear  = 0.6;   // mm — clearance between stacked bins (measure yours)

module outer() {
  cube([bin_w, bin_d, bin_h]);
}

module inner() {
  translate([wall, wall, wall])
    cube([bin_w - 2*wall, bin_d - 2*wall, bin_h - 2*wall]);
}

module body() {
  difference() { outer(); inner(); }
}

module rim_outer() {
  translate([0, 0, bin_h])
    cube([bin_w, bin_d, rim]);
}

module rim_inner() {
  translate([wall + stack_clear, wall + stack_clear, bin_h])
    cube([bin_w - 2*(wall + stack_clear),
          bin_d - 2*(wall + stack_clear), rim]);
}

module chamfer_top() {
  difference() {
    children();
    translate([-1, -1, bin_h - chamfer])
      cube([bin_w + 2, bin_d + 2, chamfer + 2]);
  }
}

union() {
  chamfer_top() { body(); }
  rim_outer();
  difference() { rim_outer(); rim_inner(); }
}

Snap-fit beam starting scaffold — adapt this for your test piece:

// Snap-Fit Cantilever Beam — Parametric Test Scaffold
// Replace the base_body and target geometry with your own design.

// ---- Key Parameters ----
beam_l      = 15;    // mm — beam length (longer = more flex)
beam_t      = 1.5;   // mm — beam thickness (thinner = more flex)
beam_w      = 6;     // mm — beam width
hook_h      = 1.2;   // mm — hook catch height (the lip that locks)
tolerance   = 0.2;   // mm — clearance for the socket opening
base_w      = 30;    // mm — base block width
base_d      = 20;    // mm — base block depth
base_h      = 4;     // mm — base block height

// Flexibility check: beam_t / beam_l should be < 0.1 for PLA
echo("Flexibility ratio:", beam_t / beam_l,
     "(target < 0.1 for reliable snap-fit)");
assert(beam_t / beam_l < 0.12,
  str("Beam too stiff: beam_t/beam_l = ", beam_t/beam_l,
      ". Reduce beam_t or increase beam_l."));

// ---- Snap-Fit Arm ----
module snap_arm() {
  union() {
    // Main cantilever beam
    cube([beam_w, beam_l, beam_t]);
    // Hook at tip
    translate([0, beam_l - hook_h, 0])
      cube([beam_w, hook_h, beam_t + hook_h]);
  }
}

// ---- Socket (receiver) ----
// The socket opening is wider than the arm by 2×tolerance
module snap_socket() {
  socket_opening = beam_w + 2 * tolerance;
  difference() {
    cube([base_w, base_d, base_h]);
    // Socket slot
    translate([(base_w - socket_opening) / 2, 0, -0.001])
      cube([socket_opening, beam_l + hook_h + tolerance, base_h + 0.002]);
  }
}

// ---- Test Assembly (render both for sizing check) ----
snap_socket();
translate([(base_w - beam_w) / 2, 0, base_h])
  snap_arm();

Assessment Questions

  1. What clip thickness and spacing values produced a reliable snap-fit for your specific printer and material?
  2. How did you balance flexibility (easy to snap and unsnap) with durability (no premature failure)?
  3. What would you change in the design if this clip needed to survive 1,000+ assembly cycles?

Appendix B: Snap-Fit Clip — Student Documentation Template

Author: ________________ Date: __________ Description: Design a snap-fit connector that joins two 3D-printed parts without external fasteners.


Design Concept

  • What two parts will your snap-fit connect?
  • Design approach (cantilever arm, torsion box, other):
  • Material selected and expected flex limits:
  • How did you verify the beam flexibility ratio (beam_t / beam_l)?

Tolerance Specifications

ParameterNominal Value (mm)Tolerance Applied (mm)Rationale
Beam thickness (beam_t)
Beam length (beam_l)
Hook height
Socket opening clearance
Contact area width

Flexibility ratio check:

beam_t / beam_l = ___ / ___ = ___
Target: < 0.1 for PLA, < 0.08 for PETG
Result: [ ] Pass   [ ] Fail — adjusted to: ___

Test Print Results

Print three variants with different tolerance values. Change only the tolerance variable between variants.

VariantTolerance (mm)Assembly effortDisassembly effortDeformation after 5 cyclesPass / Fail
V1
V2
V3

Selected tolerance value: _____ mm Justification (one paragraph — reference your test data, not intuition):


Assembly Testing Log

Cycle 1 — Initial Assembly

  • Date:
  • Effort required to snap together (easy / moderate / hard / wouldn’t snap):
  • Snap strength — resistance to pulling apart (weak / moderate / strong / won’t release):
  • Visual inspection — any deformation, whitening at bend, or cracking:

Cycle 2

  • Date:
  • Observations:

Cycle 3

  • Date:
  • Observations:

Cycle 4

  • Date:
  • Observations:

Cycle 5

  • Date:
  • Observations:

Durability Assessment

  • After 5 cycles, is the snap-fit still functional? Yes / No / Partially
  • Any permanent deformation observed? Describe:
  • Estimated service life based on observed degradation rate:

Mechanical Analysis

Answer in complete sentences:

  1. Describe the snap mechanism — explain why it works mechanically, not just that it does.

  2. What material properties enable this design? What would happen if you printed the same geometry in a rigid material with no flex (like resin)?

  3. Where are the stress concentration points in your design? How did you address them?


Reflections

  1. Did the snap-fit work as expected on the first print? If not, what surprised you?

  2. What tolerance adjustment had the most significant effect, and by how much?

  3. How would you modify this design for a clip that needs to work at outdoor temperatures (hot car in summer, cold winter)?

  4. What materials would fail with this exact geometry? Why?


Attachments Checklist

  • .scad file with parametric snap-fit module (all key dimensions as named variables)
  • Photos of test variants before assembly (labeled V1, V2, V3)
  • Photos of assembled connections for each variant
  • Photos showing any deformation after 5 cycles
  • Completed tolerance specifications table
  • Completed testing log with dates and observations

Teacher Feedback

CategoryScore (0–3)Notes
Problem & Solution — snap-fit works reliably; meets functional requirements
Design & Code Quality — parametric, mechanically sound, beam rule applied
Documentation — testing log complete; tolerance rationale explained
Total (0–9)

Appendix C: Snap-Fit Clip — Instructor Reference

Project Context

This extension project reinforces the core tolerance and snap-fit content of Lesson 8 through hands-on empirical testing. The key distinction from a standard assignment is the systematic testing approach: students must let printed test data drive their final design decisions, not intuition or first-attempt results.

Key Learning Points to Reinforce

Tolerance engineering is empirical. Published clearance values are starting points. The only reliable way to know what works on a specific printer with a specific material is to print and measure. Students who skip the test coupon step and jump straight to a final design will encounter this lesson the hard way.

The beam flexibility ratio is a design rule, not a guideline. Beam_t / beam_l < 0.1 (PLA) is derived from material yield strain. A beam that violates this ratio will either not snap (too stiff) or crack on first use (overstressed). The assert() in the starter code enforces this at render time.

Snap-fits degrade with cycles. PLA creep under repeated stress means a PLA snap-fit that works perfectly at cycle 1 may be noticeably looser at cycle 20. This is not a design failure — it’s an expected material behavior that students should document and account for.

Constraints (Enforce These)

  • Snap-fit must join two printed parts without any external fasteners
  • All key dimensions must be variables (parametric code required)
  • At least three variants must be printed and tested — no single-attempt submissions
  • Assembly must be tested over at least 5 cycles with observations recorded for each

Functional Requirements (Evaluation Criteria)

  • Parts snap together securely without over-constraint or binding
  • Connection resists separation under intended use without permanent deformation at cycle 1
  • Snap mechanism is reusable for at least 5 assembly cycles
  • Design reflects understanding of tolerance and material behavior (visible in code comments and documentation)

Assessment Notes

Strong submissions show: tolerance test data driving the final design decision (not guessing), multiple assembly cycles documented with specific observations, and a reflection that discusses material limits with reference to measured results.

Common weak areas: Single-variant testing (“it worked so I stopped”), vague reflection (“I would make it thicker”), and tolerance values with no rationale. Push back on these in feedback.

Extension opportunity: Students who finish early can investigate material property comparisons — print the same geometry in PLA and PETG (if available) and compare flex behavior and cycle durability. This connects directly to the material selection content in Lesson 5. -e


Lesson 9 — Automation and 3dm Workflows

Estimated time: 90–120 minutes


Before You Start

In Lessons 1–8, you built real, functional 3D models — phone stands, keycaps, stackable bins — and learned how parametric design lets a single .scad file produce many different variants just by changing numbers. You’ve been running builds manually: open a terminal, type 3dm build, check the output, repeat. That’s fine when you’re developing one part. But what happens when you need to build 20 variants of a part for a batch test? Or when you need to prove that every commit to your project builds correctly before you send files to a printer?

This lesson is about the next step: automation. You’ll learn to write scripts that build, verify, archive, and iterate without you sitting at the keyboard. These are real software engineering skills — the same techniques used in companies that ship physical products with embedded software. By the end of this lesson, you’ll understand how professional fabrication workflows work and be able to apply those patterns to your own projects.


Learning Objectives

By the end of this lesson you will be able to:

  • Write robust automation scripts in bash (Linux/macOS), PowerShell (Windows), and CMD (Windows legacy)
  • Use proper error handling, logging, and trap/exit patterns for unattended builds
  • Pass string and numeric parameters correctly to openscad -D from all three shells
  • Automate batch builds, archiving, and variant generation
  • Implement a watch mode that rebuilds automatically when source files change
  • Integrate 3dMake automation into CI/CD pipelines with GitHub Actions

Concept: Why Automation Matters

Before writing any code, let’s understand the problem automation solves.

The Manual Build Problem

Suppose you’re building a parametric shelf bracket that needs to be tested at three different wall thicknesses (1.2 mm, 1.6 mm, 2.0 mm) across four different bracket widths (60 mm, 80 mm, 100 mm, 120 mm). That’s 12 combinations. Running each build manually means:

  1. Open terminal
  2. Type the command with the right parameter values
  3. Wait for OpenSCAD to render
  4. Check that the output exists
  5. Rename the file so it doesn’t overwrite the last one
  6. Repeat 11 more times

This takes time, introduces human error (typos in parameter values, forgetting to rename files), and produces results that are hard to reproduce later — “which settings did I use for the 80mm bracket again?”

Automation Solves Four Problems

Repeatability: A script runs exactly the same way every time. Parameter values, file names, output locations — all defined once in code, not typed by hand each time.

Error detection: A good script notices when something goes wrong and stops immediately, rather than silently producing broken output and continuing.

Documentation: A build script is documentation. Reading a well-written script tells you exactly how the project is supposed to be built — what parameters matter, what the expected output looks like, how things are organized.

Scalability: Whether you need 12 builds or 1,200, the automation works the same way.

Automation Is a Safety Net

Think of build automation like the safety rails on a mountain trail. The trail was perfectly safe without them — but the rails mean you can focus on the view instead of watching every step. Automation removes the tedious, error-prone parts of your workflow so you can focus on design.


Step 1 — The OpenSCAD -D Flag and Parameter Passing

What the -D Flag Does

OpenSCAD’s -D flag overrides any variable in your .scad file at the command line. This is the bridge between your automation scripts and your parametric models. Instead of editing the .scad file to change a value, you pass the new value directly when you run the build.

Think of it like a recipe where the recipe card has the default quantities written in pencil. The -D flag lets you write different numbers in the margin for this particular batch — without erasing the original recipe.

# The .scad file has: width = 40;
# The -D flag overrides it to 60 for this build
openscad -D "width=60" -o output.stl src/main.scad

Numeric Parameters: Straightforward

For numeric values, the syntax is identical on all platforms:

# Works the same on Linux/macOS/Windows
openscad -D "width=50" -D "height=15" -o output.stl src/main.scad
openscad -D "width=50" -D "height=15" -D "wall=2.5" -o output.stl src/main.scad

You can pass as many -D flags as you need. Each one overrides one variable.

String Parameters: The Hard Part

String values are much trickier, and this is where most beginners get tripped up. In OpenSCAD, a string value must be surrounded by double quotes: label="FRONT". But you’re passing this string inside another string on the command line, which creates a quoting conflict.

This is the #1 source of silent failures in automation scripts. If you get the quoting wrong, OpenSCAD may accept the command without error but produce a model where the label is empty or incorrect. No error message. No warning. Just wrong output.

Why Quoting Is Different on Each Platform

Each shell — bash (Linux/macOS), PowerShell (Windows), and CMD (Windows legacy) — has its own rules for how quotes work inside quotes. There’s no single universal syntax. You need to learn the rule for each environment you use.

The underlying goal is always the same: you need OpenSCAD to receive the string label="FRONT" with the double quotes intact. Each shell provides a different way to achieve that.

Linux / macOS (bash)

The rule: Use single quotes around the entire -D value to protect inner double quotes. Single-quoted strings in bash are completely literal — nothing inside them is interpreted.

# CORRECT: single quotes around the entire -D value protect inner double quotes
openscad -D 'label="FRONT"' -o out.stl src/main.scad

# CORRECT: backslash-escaped double quotes inside a double-quoted string
openscad -D "label=\"FRONT\"" -o out.stl src/main.scad

# CORRECT: variable with proper escaping
LABEL="FRONT PANEL"
openscad -D "label=\"${LABEL}\"" -o out.stl src/main.scad

# DEBUGGING TIP: echo the command before running to verify quoting
echo "openscad -D 'label=\"${LABEL}\"' -o out.stl src/main.scad"

# WRONG — string value will be malformed; OpenSCAD may use an empty string
openscad -D "label=FRONT" -o out.stl src/main.scad    # missing inner quotes

Debugging trick: Before running a command, echo it first to see exactly what your shell will send to OpenSCAD. If the echoed command looks wrong, it is wrong — fix the quoting before running it for real.

Windows (PowerShell)

The rule: Single quotes work the same way as in bash — they protect inner double quotes. PowerShell also supports backtick (`) as an escape character inside double-quoted strings.

# CORRECT: single quotes protect inner double quotes
openscad -D 'label="FRONT"' -o out.stl src\main.scad

# CORRECT: backtick escapes for double quotes inside a double-quoted string
$label = "FRONT PANEL"
openscad -D "label=`"$label`"" -o out.stl src\main.scad

# CORRECT: build the argument string explicitly
$dArg = 'label="' + $label + '"'
openscad -D $dArg -o out.stl src\main.scad

# DEBUGGING TIP: display the argument before using it
Write-Host "D argument: $dArg"

Windows (CMD)

The rule: CMD uses doubled double-quotes ("") to produce a single literal double quote inside a string. This is the most visually confusing notation — ""FRONT"" means: open double-quote, then the word FRONT, then close double-quote.

REM CMD uses doubled double-quotes to produce a literal double-quote inside a string
openscad -D "label=""FRONT""" -o out.stl src\main.scad

REM With a variable
SET LABEL=FRONT
openscad -D "label=""%LABEL%""" -o out.stl src\main.scad

REM DEBUGGING: echo first to verify
echo label=""%LABEL%""

Common Mistake: Assuming Silent Success

OpenSCAD will often not report an error when string quoting is wrong. The variable just gets an empty string or undef as its value. If your label text disappears from the rendered model, check your quoting before anything else.


Step 2 — Robust Error Handling

What “Robust” Means

A script is robust if it handles failure gracefully: it detects when something went wrong, reports the failure clearly, and stops before making things worse. A fragile script ignores errors and continues — which often means you end up with a folder full of broken or empty output files.

The Three Failure Modes to Guard Against

Silent failure: The command runs, returns an error code, but the script doesn’t check and keeps going. You discover the problem later when the output files don’t work.

Partial output: The build starts, produces a partially-written file, then crashes. The file exists but is corrupted. Your script needs to check that the output is complete and has a reasonable size.

Cascade failure: One failure causes subsequent steps to fail too, making the error messages confusing. Stop at the first failure — don’t keep running.

Error Handling in bash

Bash has three critical safety settings that should be at the top of every automation script:

  • set -e — exit immediately if any command returns a non-zero exit code (non-zero = failure)
  • set -u — error if you reference a variable that was never defined (catches typos in variable names)
  • set -o pipefail — catch errors inside pipelines, not just the last command in the pipe

Think of these as your script’s “safety mode.” Without them, bash will happily continue running after errors. With them, the first problem causes an immediate stop.

#!/bin/bash
# build.sh — robust build script with logging and error handling

set -e           # exit immediately if any command returns a non-zero exit code
set -u           # error on use of any unset variable
set -o pipefail  # catch errors inside pipelines (not just the last command)

LOG_DIR="build/logs"
LOG_FILE="$LOG_DIR/build_$(date +%Y%m%d_%H%M%S).log"
mkdir -p "$LOG_DIR" build

# Logging function: prints with timestamp and appends to log file
log() {
  local level="$1"
  shift
  echo "[$(date +%H:%M:%S)] [$level] $*" | tee -a "$LOG_FILE"
}

# Trap: runs when any error occurs, reports which line failed
on_error() {
  log "ERROR" "Build failed at line $1. Check: $LOG_FILE"
  exit 1
}
trap 'on_error $LINENO' ERR

log "INFO" "=== Build started ==="
log "INFO" "Source: src/main.scad"

# Build — capture stderr, show on screen, and append to log
if ! openscad -o build/main.stl src/main.scad 2>&1 | tee -a "$LOG_FILE"; then
  log "ERROR" "OpenSCAD exited with error"
  exit 1
fi

# Verify the output file was actually created and has reasonable size
STL_PATH="build/main.stl"
if [ ! -f "$STL_PATH" ]; then
  log "ERROR" "STL file not created: $STL_PATH"
  exit 1
fi

STL_SIZE=$(stat -c%s "$STL_PATH")
if [ "$STL_SIZE" -lt 1000 ]; then
  log "WARN" "STL file suspiciously small: ${STL_SIZE} bytes — may be empty geometry"
fi

log "INFO" "Build complete: $STL_PATH (${STL_SIZE} bytes)"
3dm info 2>&1 | tee -a "$LOG_FILE"
log "INFO" "=== Build finished ==="

Error Handling in PowerShell

PowerShell uses try/catch blocks and checks the $LASTEXITCODE variable (which holds the exit code of the last external command) to detect failures. The key difference from bash: PowerShell doesn’t automatically stop on error — you must check $LASTEXITCODE yourself after every external command.

# build.ps1 — robust build script for Windows

param(
    [string]$Source    = "src\main.scad",
    [string]$Output    = "build\main.stl",
    [string]$LogDir    = "build\logs"
)

$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
New-Item -ItemType Directory -Force -Path $LogDir, "build" | Out-Null
$logFile = Join-Path $LogDir "build_$timestamp.log"

function Write-Log {
    param([string]$Level, [string]$Message)
    $entry = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message"
    Write-Host $entry
    Add-Content -Path $logFile -Value $entry
}

Write-Log "INFO" "=== Build started ==="
Write-Log "INFO" "Source: $Source"

try {
    $buildOutput = & openscad -o $Output $Source 2>&1
    $buildOutput | Tee-Object -FilePath $logFile -Append | Write-Host
    if ($LASTEXITCODE -ne 0) { throw "OpenSCAD returned exit code $LASTEXITCODE" }
} catch {
    Write-Log "ERROR" "Build failed: $_"
    exit 1
}

if (-not (Test-Path $Output)) {
    Write-Log "ERROR" "STL file not created: $Output"
    exit 1
}

$stlSize = (Get-Item $Output).Length
if ($stlSize -lt 1000) {
    Write-Log "WARN" "STL suspiciously small: $stlSize bytes"
}

Write-Log "INFO" "Build complete: $Output ($stlSize bytes)"
3dm info 2>&1 | Tee-Object -FilePath $logFile -Append
Write-Log "INFO" "=== Build finished ==="

Step 3 — Batch Builds and Variant Generation

The Concept: Parametric Variants at Scale

Now that you can build reliably with error handling, you can automate the generation of multiple variants. The pattern is simple: loop over a list of parameter combinations, run a build for each, name the output file to reflect the parameters used.

Good output naming is critical. A file called main.stl tells you nothing. A file called bracket_w80_h60_wall2.stl tells you exactly what parameters produced it — you can reconstruct the build command just from the filename.

Batch Build in bash

#!/bin/bash
# batch_variants.sh

set -e
set -u
set -o pipefail

OUTPUT_DIR="build/variants"
mkdir -p "$OUTPUT_DIR"

SUCCESS=0
FAIL=0
FAILED_BUILDS=()

for WIDTH in 60 80 100 120; do
  for WALL in 1.2 1.6 2.0; do
    NAME="bracket_w${WIDTH}_wall${WALL/./_}"
    OUT="$OUTPUT_DIR/${NAME}.stl"

    echo "Building: $NAME ..."
    if openscad -D "width=${WIDTH}" -D "wall=${WALL}" \
                -o "$OUT" src/main.scad 2>/dev/null; then
      echo "  OK: $OUT"
      SUCCESS=$((SUCCESS + 1))
    else
      echo "  FAILED: $NAME"
      FAIL=$((FAIL + 1))
      FAILED_BUILDS+=("$NAME")
    fi
  done
done

echo ""
echo "=== Batch complete: $SUCCESS succeeded, $FAIL failed ==="
if [ ${#FAILED_BUILDS[@]} -gt 0 ]; then
  echo "Failed builds:"
  for b in "${FAILED_BUILDS[@]}"; do
    echo "  - $b"
  done
  exit 1
fi

Batch Build in PowerShell

# batch_variants.ps1

$outputDir = "build\variants"
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null

$success = 0
$fail    = 0
$failed  = @()

foreach ($width in @(60, 80, 100, 120)) {
  foreach ($wall in @(1.2, 1.6, 2.0)) {
    $wallStr = "$wall" -replace '\.', '_'
    $name    = "bracket_w${width}_wall${wallStr}"
    $out     = "$outputDir\${name}.stl"

    Write-Host "Building: $name ..."
    & openscad -D "width=$width" -D "wall=$wall" -o $out src\main.scad 2>$null
    if ($LASTEXITCODE -eq 0 -and (Test-Path $out)) {
      Write-Host "  OK: $out"
      $success++
    } else {
      Write-Host "  FAILED: $name"
      $fail++
      $failed += $name
    }
  }
}

Write-Host ""
Write-Host "=== Batch complete: $success succeeded, $fail failed ==="
if ($failed.Count -gt 0) {
  Write-Host "Failed builds:"
  $failed | ForEach-Object { Write-Host "  - $_" }
  exit 1
}

Step 4 — Timestamped Archiving

Why Archive Builds?

Imagine you printed a part two weeks ago that fit perfectly. Now you’ve made some changes to the model, and the new version doesn’t fit. You need to go back to the version that worked — but you only have one build/main.stl file, which has been overwritten.

Timestamped archiving solves this. Every successful build is saved with a timestamp in its filename. You can always go back to any previous version. Over time, you build a history of exactly when each change was made.

Archive Script

#!/bin/bash
# archive_build.sh

set -e
set -u

ARCHIVE_DIR="build/archive"
mkdir -p "$ARCHIVE_DIR"

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
ARCHIVE_NAME="main_${TIMESTAMP}.stl"

# Build
3dm build

# Archive the successful result
cp build/main.stl "$ARCHIVE_DIR/$ARCHIVE_NAME"
echo "Archived: $ARCHIVE_DIR/$ARCHIVE_NAME"

# Optional: remove archives older than 30 days
find "$ARCHIVE_DIR" -name "*.stl" -mtime +30 -delete
echo "Old archives cleaned."

Step 5 — Watch Mode

The Concept: Automatic Rebuild on Save

Watch mode is a script that monitors your source files and automatically runs a build whenever a file changes. Instead of switching to your terminal and running 3dm build every time you save a change in your editor, the script does it for you.

This creates a tight feedback loop: save your .scad file, glance at the terminal, and the new build result is already there. It’s like having an assistant who runs the build the instant you save.

How Watch Mode Works

There are two approaches:

Poll-based: Check the file’s modification timestamp every few seconds. If it changed since the last check, trigger a rebuild. Simple to implement; works everywhere. Slightly wasteful — you’re checking constantly even when nothing changes.

Event-based: The operating system notifies you the instant a file changes (using inotify on Linux, FSEvents on macOS, FileSystemWatcher on Windows). More efficient; responds immediately. More complex to set up.

For development workflows, the poll-based approach is usually good enough.

#!/bin/bash
# watch_and_build.sh — poll-based watch mode

set -u

WATCH_FILE="src/main.scad"
POLL_INTERVAL=2   # seconds between checks

echo "Watching: $WATCH_FILE (Ctrl+C to stop)"

LAST_MOD=""

while true; do
  CURRENT_MOD=$(stat -c%Y "$WATCH_FILE" 2>/dev/null || echo "0")

  if [ "$CURRENT_MOD" != "$LAST_MOD" ]; then
    LAST_MOD="$CURRENT_MOD"
    if [ -n "$LAST_MOD" ] && [ "$LAST_MOD" != "0" ]; then
      echo ""
      echo "[$(date +%H:%M:%S)] Change detected — rebuilding..."
      3dm build && echo "  Build OK" || echo "  Build FAILED"
    fi
  fi

  sleep "$POLL_INTERVAL"
done
# watch_and_build.ps1 — poll-based watch mode for Windows

$watchFile    = "src\main.scad"
$pollInterval = 2  # seconds

Write-Host "Watching: $watchFile (Ctrl+C to stop)"

$lastMod = $null

while ($true) {
    if (Test-Path $watchFile) {
        $currentMod = (Get-Item $watchFile).LastWriteTime

        if ($currentMod -ne $lastMod) {
            $lastMod = $currentMod
            if ($null -ne $lastMod) {
                Write-Host ""
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Change detected — rebuilding..."
                & 3dm build
                if ($LASTEXITCODE -eq 0) {
                    Write-Host "  Build OK"
                } else {
                    Write-Host "  Build FAILED"
                }
            }
        }
    }
    Start-Sleep -Seconds $pollInterval
}

Step 6 — CI/CD Integration

What CI/CD Means

CI/CD stands for Continuous Integration / Continuous Deployment. In software development, CI/CD means that every time you push code to a shared repository, an automated system builds and tests your project in a clean environment — not on your computer, but on a server in the cloud.

For a 3D printing project, CI/CD means:

  • Every time you commit a change to your .scad files, GitHub automatically builds your STL
  • If the build fails (syntax error, empty geometry, etc.), you get an email notification immediately
  • The built STL is saved as a downloadable artifact — you can prove to anyone that this exact commit produced this exact file
  • You can track exactly when changes were made and whether they broke anything

This sounds like overkill for a hobby project — but even for personal projects, CI/CD is a useful safety net. It catches problems you might miss locally, and it creates a reliable record of your design history.

How GitHub Actions Works

GitHub Actions is a CI/CD system built into GitHub. You define a “workflow” in a YAML file inside your repository. The workflow runs automatically on events you specify — such as every push to the main branch.

The workflow runs on a fresh Ubuntu virtual machine in GitHub’s cloud. It has no memory of previous builds. Every run starts from scratch: clone the repository, install dependencies, run the build, save the output.

# .github/workflows/build.yml
# This file tells GitHub Actions what to do on every push.

name: Build STL

on:
  push:
    paths:
      - "src/**" # only trigger when .scad files change

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install OpenSCAD
        run: |
          sudo apt-get update
          sudo apt-get install -y openscad

      - name: Install 3dMake
        run: curl -fsSL https://get.3dmake.dev | bash

      - name: Build
        run: |
          3dm build
          3dm info

      - name: Verify STL exists and has reasonable size
        run: |
          test -f build/main.stl
          SIZE=$(stat -c%s build/main.stl)
          echo "STL size: $SIZE bytes"
          test "$SIZE" -gt 1000

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: stl-output-${{ github.sha }}
          path: build/main.stl

When this is set up, every push to the repository triggers a fresh build in GitHub’s cloud. If the build fails, you get an email notification. The built STL is saved as an artifact you can download directly from the GitHub interface.

What Each Section Does

on: push: paths: — Only run the workflow when files in the src/ directory change. This prevents the workflow from running when you update the README, for example.

runs-on: ubuntu-latest — Use GitHub’s latest Ubuntu virtual machine. This is a standard Linux environment with nothing pre-installed.

actions/checkout@v4 — Clone your repository into the virtual machine. Without this, the machine has no idea what your project looks like.

Install OpenSCAD / Install 3dMake — Install your build tools. Every run starts fresh, so tools must be installed every time.

Build — Run your build. If this fails (non-zero exit code), the whole workflow fails.

Verify STL exists and has reasonable size — An explicit sanity check. test -f verifies the file exists. test "$SIZE" -gt 1000 verifies it’s not empty.

Upload artifact — Save the built STL so you can download it from GitHub. The ${{ github.sha }} part includes the commit hash in the artifact name, so you always know which commit produced which STL.


Exercises

Exercise 9.1: Adapt the batch_variants script to your platform. Generate your phone stand at 5 different stand_angle values (30°, 45°, 60°, 70°, 80°). Log the bounding box for each to a file.

Exercise 9.2: Write a build script in your preferred shell that: (1) builds the model, (2) verifies the STL size is > 10,000 bytes, (3) archives the result with a timestamp if the build succeeds, (4) prints a failure message to the console if it fails.

Exercise 9.3 (Advanced): Create a parametric Makefile (Linux/macOS) or a PowerShell Invoke-Build task file (Windows) with separate targets: build, clean, variants, archive, and test. Running make all should run all targets in the correct order.


Quiz — Lesson 3dMake.9 (15 questions)

  1. What does set -e do in a bash script?
  2. Why is passing string parameters with -D more complex than passing numeric parameters?
  3. What does trap 'on_error $LINENO' ERR do in a bash script?
  4. What is the correct way to pass label="FRONT" as an OpenSCAD -D argument in bash?
  5. What does set -u protect against?
  6. How would you verify that an output STL was actually created in a build script?
  7. What is a “silent failure” in the context of automation, and how do you prevent one?
  8. In PowerShell, what character is used to escape a double quote inside a double-quoted string?
  9. What does $LASTEXITCODE contain in a PowerShell script after running an external command?
  10. Describe the purpose of a timestamped build archive and when you would use it.
  11. What is CI/CD, and how does it apply to a 3D printing project workflow?
  12. True or False: In CMD, doubled double-quotes inside a quoted string produce a single literal double-quote.
  13. Explain the difference between a poll-based file watcher and an event-based file watcher. What are the trade-offs?
  14. In a GitHub Actions workflow, what does on: push: paths: - 'src/**' specify?
  15. If a batch build script runs 10 builds and each may succeed or fail independently, describe the logic for reporting: total built, total failed, and which specific builds failed.

Extension Problems (15)

  1. Write a batch build script that tests 10 parameter combinations and generates a summary report with pass/fail status for each.
  2. Create a “golden master” verification script: build your reference model, save the bounding box, then verify that future builds match those dimensions within 0.1 mm.
  3. Implement the timestamped archive system and add a rotation policy: automatically delete archives older than 30 days.
  4. Build a Git pre-commit hook that runs 3dm build and fails the commit if the build doesn’t succeed.
  5. Create a build dashboard: a script that runs all your projects’ builds, collects their 3dm info outputs, and formats them into a summary report.
  6. Implement parallel builds: run multiple OpenSCAD builds simultaneously using background processes or PowerShell jobs. Measure the speedup.
  7. Create a “changelog” generator: compare the bounding boxes of all archived builds and generate a list of which builds had dimension changes.
  8. Write a CI/CD pipeline configuration for GitLab CI or Bitbucket Pipelines (instead of GitHub Actions).
  9. Build a build notification system: send a Slack message or email when a build fails.
  10. Create a “test suite” of deliberately bad .scad files (empty geometry, non-manifold shapes, syntax errors) and verify your build script catches all of them.
  11. Implement semantic versioning in your build system: automatically increment a patch version number on each successful build.
  12. Write a multi-platform build script that detects the current OS and uses the appropriate commands (bash on Linux/macOS, PowerShell on Windows).
  13. Create a build matrix: for each of 5 designs × 4 materials, build the design with material-specific parameters and verify each output.
  14. Implement a “regression test”: store the bounding box of each successful build, and flag any build where the bounding box changes unexpectedly.
  15. Research and implement “build caching”: skip rebuilds when the source file hasn’t changed since the last successful build.

References and Helpful Resources

  • Bash Reference Manual — https://www.gnu.org/software/bash/manual/bash.html

  • PowerShell Documentation — https://docs.microsoft.com/en-us/powershell/

  • GitHub Actions Documentation — https://docs.github.com/en/actions

  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake

Supplemental Resources

  • Programming with OpenSCAD EPUB Textbook — assets/Programming_with_OpenSCAD.epub
  • 3DMake GitHub Repository — https://github.com/tdeck/3dmake
  • OpenSCAD User Manual — https://en.wikibooks.org/wiki/OpenSCAD_User_Manual -e

Lesson 10 — Hands-On Practice Exercises and Troubleshooting

Estimated time: 120–150 minutes


Before You Start

You’ve built a substantial toolkit over the first nine lessons: primitives, CSG operations, parametric modules, transforms, tolerances, interlocking features, automation scripts. This lesson is where those skills converge. Rather than introducing a single new concept, Lesson 10 is about depth — applying advanced OpenSCAD features to real design problems, understanding when to use each tool, and developing the troubleshooting instincts that separate experienced designers from beginners.

The advanced features in this lesson — hull(), minkowski(), projection(), surface(), children(), and search() — are not obscure corners of OpenSCAD. They’re the tools that unlock the difference between “looks like a 3D-printed object” and “looks like a professionally designed product.”


Learning Objectives

By the end of this lesson you will be able to:

  • Apply hull() and minkowski() with awareness of their performance cost
  • Use $preview to conditionally disable slow operations during development
  • Create 2D templates with projection() for drilling guides and laser cutting
  • Diagnose and fix all four common types of non-manifold geometry
  • Apply surface() for height-map terrain and embossed artwork
  • Write advanced parametric assemblies using children() and $children
  • Use search() and lookup() for data-driven parametric design

Concept: From Functional to Refined

Up to now, most designs have used right-angle geometry — boxes, cylinders, straight edges. This produces functional parts, but real products rarely look like that. Consider a smartphone: it has rounded corners, smooth transitions between surfaces, organic curves. None of those were added by accident — each one was a deliberate design choice that improves how the product feels in your hand and looks on a shelf.

The tools in this lesson let you add that kind of refinement to your OpenSCAD designs without abandoning the parametric approach. You’ll still define everything with numbers and variables — but the shapes those numbers produce will be much more sophisticated.


Step 1 — hull() for Organic Shapes

What hull() Does

Imagine stretching a rubber band around several objects placed on a table. The rubber band forms the tightest possible loop that touches all of them, following the outside curve of each object. This is exactly what hull() does in 3D: it computes the convex hull — the smallest convex shape that contains all its children.

“Convex” means the shape never curves inward. A sphere is convex. A donut is not (it has a hole — a concave feature). The convex hull of two spheres is like a capsule — the two spheres connected by a smooth, outward-curving surface.

When to Use hull()

hull() is excellent for:

  • Smooth transitions between two different shapes at different heights (like the neck of a bottle smoothly widening into the body)
  • Rounded boxes — place a small sphere at each corner, take the hull, and every corner and edge becomes rounded
  • Organic profiles — aerofoil cross-sections, ergonomic handles, teardrop shapes
  • Anywhere you want to avoid sharp 90-degree corners without adding complex geometry

hull() is much faster than minkowski() (covered in Step 2) and should be your first choice for organic shapes.

Important Limitation

hull() only produces convex shapes. If you need a shape that curves inward — a saddle, a cup, a grip with a waist — hull() alone can’t do it. You’d need to use hull() as a building block and then use difference() to carve in the concave features.

Example 1: Smooth Transition Between a Hexagonal Cylinder and a Sphere

// hull() between two different shapes at different heights
// Creates a smooth transition (like a funnel or transition piece)
hull() {
  cylinder(r=20, h=1, $fn=6);       // hexagon at bottom
  translate([0, 0, 30])
    sphere(r=8, $fn=32);             // sphere at top
}

This produces a smooth funnel-like shape — hexagonal at the base, tapering to a sphere at the top. Without hull(), you’d need complex math to define the intermediate surface.

Example 2: Rounded Box Using hull() of 8 Spheres

Place one sphere at each of the 8 corners; hull() fills the space between them, rounding every corner and edge by the sphere radius.

r = 5;  // corner radius
w = 40; d = 30; h = 20;

hull() {
  for (x = [r, w-r]) {
    for (y = [r, d-r]) {
      translate([x, y, 0]) sphere(r=r, $fn=24);
      translate([x, y, h]) sphere(r=r, $fn=24);
    }
  }
}

The sphere radius r controls how rounded the corners are. Setting r=1 gives subtle rounding; r=10 gives very rounded, pillow-like corners.

Example 3: Wing / Aerofoil Profile

// hull() of two cylinders at different positions and radii
// produces a smooth aerofoil cross-section
translate([0, 50, 0])
hull() {
  cylinder(r=6, h=2, $fn=32);            // leading edge (round)
  translate([40, 0, 0])
    cylinder(r=1, h=2, $fn=16);          // trailing edge (sharp)
}

The larger cylinder becomes the rounded leading edge; the small cylinder becomes the sharp trailing edge. hull() constructs the smooth surface connecting them automatically.


Step 2 — minkowski() — Performance Warning and Pattern

What Minkowski Sum Means

minkowski() computes the Minkowski sum: it places a copy of the secondary shape at every point on the surface of the primary shape, then takes the union of all those copies. The result is as if you “rolled” the secondary shape across every surface, corner, and edge of the primary shape.

The practical effect: if your primary shape is a cube and your secondary shape is a small sphere, the result is a cube with perfectly rounded corners and edges — where the rounding radius equals the sphere radius.

This is mathematically precise rounding that handles any geometry, including complex shapes with many faces. It’s also how you create “offset” versions of shapes — the Minkowski sum with a sphere produces a shape that is uniformly larger in all directions by the sphere’s radius.

The Performance Warning

Here’s the problem: the face count of the Minkowski result is roughly the product of the face counts of the two input shapes. A cube has 6 faces. A sphere with $fn=32 has about 1,000 faces. The Minkowski sum has roughly 6,000 faces to compute. Now substitute a complex curved primary shape with 500 faces, and you’re computing 500,000 faces. This can take minutes on a modern computer.

⚠ A complex primary shape combined with a sphere at $fn=64 can take many minutes to render. Always use $preview to skip the minkowski() call during development.

$preview: Fast Development, Accurate Rendering

OpenSCAD has two rendering modes:

  • F5 (Preview): Fast, approximate. Uses OpenCSG rendering. $preview is true.
  • F6 (Full Render): Exact, uses CGAL library. Much slower but produces accurate manifold geometry for export. $preview is false.

Use $preview as a conditional: show a fast placeholder during development (F5), and run the expensive minkowski() only during final render (F6).

Version note: $preview is available in OpenSCAD 2019.05 and later. In earlier versions it is undefined (treated as false). If you are using an older version, omit the $preview guard and only run F6 when you need the final result.

// $preview is TRUE during F5 (fast preview) and FALSE during F6 (full render).
// Use it to swap between a fast placeholder and the full Minkowski computation.

module rounded_box(w, d, h, r=4) {
  if ($preview) {
    // Fast preview mode: plain cube — renders instantly.
    // Color it orange as a reminder this is NOT the final shape.
    color("orange", 0.6) cube([w, d, h]);
  } else {
    // Full render mode: proper Minkowski sum.
    // Keep the secondary sphere LOW-POLY to limit face-count explosion.
    minkowski() {
      cube([w - 2*r, d - 2*r, h - r]);
      sphere(r=r, $fn=12);  // keep $fn LOW for minkowski — 12 is usually enough
    }
  }
}

rounded_box(50, 40, 20, r=5);

hull() as a Faster minkowski() Alternative

hull() only works for convex shapes, but it is far faster than minkowski(). For a simple rounded box you can get an equivalent result by placing a sphere at each corner and taking the hull:

translate([0, 60, 0])
hull() {
  // Equivalent to minkowski(cube, sphere) — much faster for convex shapes
  r = 4;
  w = 50; d = 40; h = 16;
  for (x = [r, w-r]) for (y = [r, d-r]) for (z = [r, h-r]) {
    translate([x, y, z]) sphere(r=r, $fn=12);
  }
}

Performance guidelines for minkowski():

Primary shape facesSecondary $fnExpected render time
< 1008–16< 1 second
100–5008–161–10 seconds
500–2000810–60 seconds
> 2000anyMinutes to hours — avoid

Rule of thumb: If the primary shape is a simple primitive (cube, cylinder, basic extrusion), minkowski() is manageable. If the primary shape is itself a complex CSG result, use hull() instead.


Step 3 — projection() for 2D Templates

The Concept: Flattening 3D to 2D

projection() takes a 3D shape and flattens it onto the XY plane, producing a 2D outline. Think of shining a light straight down onto a 3D object: the shadow it casts on the floor is the projection.

This is useful in fabrication contexts because real-world assembly often requires 2D templates:

  • A drilling template — print a flat sheet that shows exactly where to drill holes in a wall, shelf, or PCB
  • A laser-cut profile — export the 2D shape of a part as a DXF for a laser cutter to follow
  • A footprint check — verify that your design will actually fit in the space you have before printing
  • A CNC machining path — export a cross-section as a DXF for a CNC router

projection() has two modes:

  • cut=false — projects the full silhouette (shadow from above): every part of the shape, regardless of height
  • cut=true — projects a cross-section at z=0: only the parts of the shape at exactly that height plane
// projection(cut=false) — complete silhouette (shadow from above)
// projection(cut=true)  — cross-section at z=0 (slice through the model)

module phone_stand_example() {
  cube([90, 70, 5]);
  translate([15, 20, 5]) cylinder(r=5, h=35, $fn=24);  // mounting post A
  translate([75, 20, 5]) cylinder(r=5, h=35, $fn=24);  // mounting post B
}

// 3D model (for printing)
phone_stand_example();

// 2D silhouette (footprint) — placed beside the 3D model for comparison
color("LightGreen")
translate([110, 0, 0])
  linear_extrude(1)   // 1mm thick so it is visible in 3D preview
    projection(cut=false)
      phone_stand_example();

// Cross-section at z=3 — shows internal structure at that height
color("LightCoral")
translate([220, 0, 0])
  linear_extrude(1)
    projection(cut=true)
      translate([0, 0, -3])  // shift model so the cut falls at z=3 of the part
        phone_stand_example();

Exporting DXF for Laser Cutting or CNC

Note: 3dm is designed for building STL output. Use the openscad CLI directly for DXF export — do not use 3dm build for this step.

# Linux / macOS
openscad -o template.dxf src/template_projection.scad

# Windows (PowerShell or CMD)
openscad -o template.dxf src\\template_projection.scad

Best practice: keep projection files separate. Create a dedicated .scad file for DXF export that imports your main model and wraps it in projection(). This keeps your main model file clean.

// src/template_projection.scad
// This file is used exclusively for DXF export.
// It should contain only projection() — no 3D geometry.

use <../src/main.scad>

// Project the full silhouette
projection(cut=false)
  main_assembly();

// Add mounting-hole markers as circles.
// DXF circles are standard and ready for CNC drilling.
hole_positions = [[10, 10], [80, 10], [10, 60], [80, 60]];
for (pos = hole_positions) {
  translate(pos)
    circle(r=1.75, $fn=16);  // 3.5 mm diameter holes
}

Step 4 — Diagnosing Non-Manifold Geometry

What “Manifold” Means and Why It Matters

A mesh is manifold (also called “watertight”) when it follows two strict rules:

  1. Every edge is shared by exactly two faces — no more, no fewer
  2. The surface has no holes, zero-thickness walls, or self-intersections

Think of a manifold mesh like a sealed plastic bag. You can fill it with water and it won’t leak anywhere. Every point on the surface is clearly either “inside” or “outside.” Slicers need this to determine which areas to fill with material.

A non-manifold mesh is like a bag with a hole in it, or two bags fused at a single edge with no material connecting them. Slicers can’t slice it correctly — they might produce missing layers, extra walls, or simply refuse to import the file.

How OpenSCAD Produces Non-Manifold Geometry

OpenSCAD’s CSG operations are mathematically defined, but floating-point arithmetic and co-planar face interactions can create subtle mesh problems. The four most common causes:

Problem 1 — Co-Planar Faces in difference()

When the cutter exactly coincides with the face of the base shape, OpenSCAD cannot determine which side of the face to keep. The result is an ambiguous, possibly non-manifold edge. Fix: extend the cutter by 0.001 mm on each side so it clearly passes through the material.

difference() {
  cube([20, 20, 20]);
  translate([5, 5, -0.001])           // extend 0.001 below base
    cylinder(r=5, h=20.002, $fn=24);  // extend 0.001 above top
}

This is the same 0.001 mm rule introduced in Lesson 2. It’s worth repeating because forgetting it is the most common cause of non-manifold geometry in student work.

Problem 2 — Zero-Thickness or Negative-Thickness Walls

If your wall thickness calculation ever produces zero or a negative number, the resulting geometry has no material — creating a degenerate mesh.

module thin_wall_box(w, d, h, wall=2) {
  assert(wall > 0 && wall < min(w,d)/2,
    str("wall must be 0 < wall < ", min(w,d)/2, ", got: ", wall));
  difference() {
    cube([w, d, h]);
    translate([wall, wall, wall])
      cube([w - 2*wall, d - 2*wall, h]);  // open top — valid manifold
  }
}

The assert() guard here catches the problem before it reaches the renderer. This is better than discovering it in the slicer.

Problem 3 — Shapes That Only Touch (Not Overlap)

Two shapes that share a face but do not overlap create a non-manifold edge — an edge that belongs to faces from both shapes but with no clear “inside.” Fix: overlap by 0.001 mm and wrap in union().

module two_boxes() {
  union() {
    cube([10, 10, 10]);
    translate([10 - 0.001, 0, 0])   // overlap by 0.001 — not just touch
      cube([10, 10, 10]);
  }
}

Problem 4 — Inverted Normals from Negative scale()

scale() with a negative value flips face normals (the direction each face “points”), creating inside-out geometry. The shape looks correct in the preview but has every face pointing the wrong direction — which slicers interpret as solid material where there should be empty space.

// WRONG — negative scale flips normals:
// scale([-1, 1, 1]) some_module();

// CORRECT — mirror() preserves normals:
mirror([1, 0, 0]) some_module();

Debugging Tip: The Ghost Modifier

// Use the % modifier to render a shape as a transparent ghost
// so you can see inside the model and verify cutter placement.
difference() {
  cube([20, 20, 20]);
  % cylinder(r=5, h=25, $fn=24);  // ghost the cutter
}

The % modifier makes the cutter semi-transparent in preview mode, letting you visually verify it’s positioned and sized correctly before committing to the render.

Manifold Check Workflow

# Build the STL
3dm build

# OpenSCAD prints manifold warnings to the console, e.g.:
#   WARNING: Object may not be a valid 2-manifold ...
# Check for this message after every build.

# For more detail, use admesh:
# Linux:   apt install admesh
# macOS:   brew install admesh
admesh --analyze build/main.stl

# Or open the STL in PrusaSlicer and enable "Check for geometry errors"
# to see orange highlights on problem edges.

⚠ The correct OpenSCAD manifold warning is “WARNING: Object may not be a valid 2-manifold”. Searching for any other string will cause you to miss real errors.


Step 5 — surface() for Height-Map Geometry

The Concept: Images as 3D Terrain

surface() reads a grayscale image or a .dat data file and creates a 3D surface where pixel brightness maps to Z height. Black pixels (value 0) produce no height; white pixels (value 255) produce maximum height. Every shade of gray in between produces an intermediate height, interpolated smoothly between pixels.

Think of a topographic map where elevation is encoded in color — surface() works exactly like that. You can create terrain landscapes from satellite elevation data, embossed artwork from any image, textured panels from grayscale photographs, or precise surface profiles from engineering data.

Why surface() Is Powerful

Traditional CSG modeling works from the outside in: you define shapes geometrically and combine them. surface() lets you work from data — the shape emerges from a dataset rather than from geometric primitives. This is how architectural visualization software creates terrain, how prosthetic designers create textured grip surfaces, and how engineers create test panels with complex surface profiles.

Example 1: Minimal Self-Contained surface() from a .dat File

Save the matrix below as terrain.dat in the same folder as your .scad file, then run the surface() call. No external image editor required.

 0  10  20  10   0
10  40  60  40  10
20  60 100  60  20
10  40  60  40  10
 0  10  20  10   0
// In your .scad file:
scale([5, 5, 0.3])   // each cell = 5 mm wide; height scaled from 0–100
  surface(file="terrain.dat", center=true);

This produces a small mountain shape — highest at the center, tapering outward. The scale() controls the physical dimensions: X/Y scale determines how wide each data cell becomes, and Z scale determines the vertical exaggeration.

Example 2: Embossed Logo Panel

Create a grayscale PNG (logo = white, background = black), save it as src/logo_heightmap.png, then use the module below.

module logo_panel(panel_w=60, panel_d=40, panel_h=3, relief=1.5) {
  // Base plate
  cube([panel_w, panel_d, panel_h]);

  // Embossed surface on top.
  // Assumes logo_heightmap.png is 100×100 pixels; scale to fit the panel.
  translate([0, 0, panel_h])
    scale([panel_w/100, panel_d/100, relief/255])
      surface(file="src/logo_heightmap.png", center=false, invert=false);
}

logo_panel();

surface() supports PNG (grayscale or colour — uses luminance) and .dat (whitespace-separated matrix). Always check that the image dimensions match the aspect ratio you want before scaling.


Step 6 — Advanced: children() and Custom Container Modules

The Concept: Modules That Accept Geometry as Input

So far, every module you’ve written produces geometry from parameters. children() lets you write modules that wrap geometry — they accept shapes as input and do something with them. This is like writing a picture frame that works with any picture, rather than one specific picture built into the frame.

The pattern is called a container module: a module that defines a structural context (a base plate, a grid, a mounting system) and places its children in that context. The caller provides the geometry; the module provides the infrastructure.

$children: How Many Children Were Passed

$children is an automatic variable that contains the count of child objects passed to a module. You can use it to loop over children with children(i) to access each one individually by index (0-based).

Example 1: mounted_on_plate — Place Any Geometry on a Base with Corner Posts

module mounted_on_plate(plate_w, plate_d, plate_h=3, post_h=5) {
  // Base plate
  color("LightGray")
    cube([plate_w, plate_d, plate_h]);

  // Corner mounting posts
  for (x = [5, plate_w - 5]) {
    for (y = [5, plate_d - 5]) {
      translate([x, y, plate_h])
        cylinder(r=3, h=post_h, $fn=16);
    }
  }

  // Child geometry sits on top of the posts
  translate([0, 0, plate_h + post_h])
    children();
}

// Usage: any geometry wrapped in mounted_on_plate()
mounted_on_plate(80, 60, plate_h=3, post_h=8) {
  cylinder(r=15, h=20, $fn=32);
}

children() here is called without an index, which passes all children as a group. The cylinder in the usage example will be placed on top of the posts — without the module knowing or caring what shape it is.

Example 2: repeat_children — Tile Multiple Named Children in a Grid

$children gives you the count of children passed. Use children(i) to render the i-th child individually.

module repeat_children(n=3, spacing=25) {
  for (i = [0 : $children - 1]) {
    for (j = [0 : n - 1]) {
      translate([j * spacing, i * spacing, 0])
        children(i);  // render the i-th child
    }
  }
}

translate([0, 100, 0])
repeat_children(n=4, spacing=20) {
  sphere(r=5, $fn=16);           // child 0
  cylinder(r=4, h=10, $fn=16);   // child 1
  cube([8, 8, 6]);                // child 2
}

This tiles each child shape in its own row — spheres in the first row, cylinders in the second, cubes in the third — repeated 4 times horizontally. The module doesn’t know what shapes it’s tiling; it just repeats whatever is passed to it.

✓ OpenSCAD does not expose bounding-box queries at runtime. Always pass dimensions explicitly to container modules rather than trying to compute them from children.


The Concept: Data-Driven Parametric Design

So far, parametric design meant: change a number, the shape changes. This step takes it further: data-driven design means the shape is determined by structured data — tables, lists, databases of values.

Instead of hardcoding density = 1.24 for PLA and remembering to change it manually when you switch materials, you define a material table and let the code look up the right values automatically. The design reacts to the material choice; you just change one variable.

This is how professional parametric CAD systems work. A single master file can describe a family of parts at different sizes, materials, and configurations — all driven by lookup tables.

lookup(): Smooth Interpolation from a Table

lookup() finds an output value by interpolating between entries in a [input, output] table. If the input falls between two entries, the output is linearly interpolated between them.

// Temperature-to-fan-speed lookup table
speed_table = [
  [0,   0],   //  0°C -> fan off
  [40,  0],   // 40°C -> fan off
  [50, 50],   // 50°C -> 50% speed
  [60, 80],   // 60°C -> 80% speed
  [70, 100]   // 70°C -> full speed
];

temp = 55;
fan_speed = lookup(temp, speed_table);
echo("Fan speed at", temp, "°C:", fan_speed, "%");  // -> 65%

lookup() is especially useful for smoothly varying geometric properties — rounding radii that increase with part size, wall thicknesses that scale with load, fin counts that increase with diameter.

search(): Exact Match in a List

search() finds the index of a value in a list, enabling exact-match lookup for categorical data like material names.

search() returns a list of lists. Check len(matches[0]) > 0 for a valid result — idx != [] does not work correctly in OpenSCAD.

materials = ["PLA",  "PETG", "ABS",  "TPU",  "Nylon"];
densities = [ 1.24,   1.27,   1.05,   1.20,   1.14];

selected = "PETG";
idx = search([selected], materials)[0];
density = densities[idx];
echo(str(selected, " density: ", density, " g/cm³"));

Example 3: Print Cost Estimator with search() and assert()

This module demonstrates the full pattern: a lookup table for material properties, search() to find the right row, assert() to catch invalid material names, and computed geometry that reacts to all of it.

module print_cost_label(volume_mm3, material="PLA") {
  materials = ["PLA",  "PETG", "ABS",  "TPU",  "Nylon"];
  densities = [ 1.24,   1.27,   1.05,   1.20,   1.14];
  costs_g   = [ 0.020,  0.025,  0.018,  0.035,  0.045];

  // search() returns a list of lists.
  // matches[0] is the first result: an index on success, [] on failure.
  matches = search([material], materials);
  assert(len(matches[0]) > 0,
    str("Unknown material: \"", material, "\". Valid: ", materials));
  idx = matches[0];

  mass_g = (volume_mm3 / 1000) * densities[idx];
  cost   = mass_g * costs_g[idx];
  label  = str(material, ": ", round(mass_g * 10) / 10, "g / $",
               round(cost * 100) / 100);

  echo("Cost estimate:", label);
  linear_extrude(1)
    text(label, size=4, font="Liberation Sans", halign="center");
}

print_cost_label(12000, "PETG");

Exercise Set A: Phone Stand

A1 — Hull Transition

Add a smooth hull() transition between the base plate and the mounting post:

hull() {
  translate([15, 20, 0]) cylinder(r=8, h=1, $fn=32);   // post footprint on base
  translate([15, 20, 5]) cylinder(r=5, h=35, $fn=24);  // actual post
}

A2 — Tolerance Stack-Up

Measure the three main structural parts of your phone stand and record them in a table. Calculate worst-case stack-up:

Worst case = sum of all individual tolerances

Example for three parts each at ±0.15 mm: 0.15 + 0.15 + 0.15 = ±0.45 mm total

Document your own measurements in a similar table.

A3 — Add a Cable Slot

Extend your phone stand design with a cable slot through the base:

cable_slot_w  = 12;   // mm
cable_slot_d  = 5;    // mm
cable_slot_z  = -0.001;

// Add inside your main difference() block:
translate([base_w/2 - cable_slot_w/2, 0, cable_slot_z])
  cube([cable_slot_w, cable_slot_d, base_h + 0.002]);

Exercise Set B: Keycap with Text

B1 — Build a Mechanical Keyboard Keycap

// Parametric keycap for Cherry MX switches
key_w      = 18;
key_d      = 18;
key_h      = 7;
stem_r     = 2.75;  // MX stem: 5.5 mm diameter
stem_h     = 3.8;
wall       = 1.5;
label_text = "A";

module keycap() {
  difference() {
    // Keycap body with slight top curve
    hull() {
      cube([key_w, key_d, key_h - 2], center=true);
      translate([0, 0, 1]) cube([key_w - 2, key_d - 2, key_h], center=true);
    }
    // Hollow inside
    translate([0, 0, -wall])
      cube([key_w - 2*wall, key_d - 2*wall, key_h], center=true);
    // MX stem hole
    translate([0, 0, -(key_h/2 + 0.001)])
      cylinder(r=stem_r + 0.1, h=stem_h + 0.001, $fn=16);
  }
}

module stem_mount() {
  translate([0, 0, -(key_h/2 + stem_h)])
    difference() {
      cylinder(r=stem_r + wall, h=stem_h, $fn=16);
      cylinder(r=stem_r, h=stem_h + 0.001, $fn=16);
    }
}

keycap();
stem_mount();

// Engrave label on top
translate([0, 0, key_h/2 - 0.8])
  linear_extrude(1.2)
    text(label_text, size=8, font="Liberation Sans:style=Bold",
         halign="center", valign="center", $fn=4);

B2 — Validate with 3dm info24

3dm info

Document what the model description reports and compare it to your design intent.

B3 — Print and Test

Print the keycap and test it on a Cherry MX switch (or compatible). If the stem is too tight, increase the clearance from stem_r + 0.1 to stem_r + 0.15. If too loose, decrease to stem_r + 0.05.


Exercise Set C: Stackable Bins

C1 — Build a Three-Size Bin Set

// Small bin
translate([0, 0, 0])
  bin_assembly(bin_w=60, bin_d=45, bin_h=30);

// Medium bin
translate([80, 0, 0])
  bin_assembly(bin_w=80, bin_d=60, bin_h=40);

// Large bin
translate([180, 0, 0])
  bin_assembly(bin_w=100, bin_d=80, bin_h=50);

C2 — Diagnose and Fix Non-Manifold Geometry

Non-manifold geometry occurs when faces share edges inconsistently (T-junctions, missing faces, zero-thickness walls). A common cause is two shapes that touch at exactly one face:

// PROBLEM: two cubes share a face exactly — may produce a non-manifold edge
cube([20, 20, 10]);
translate([20, 0, 0]) cube([20, 20, 10]);  // touching at x=20

// FIX 1: use union()
union() {
  cube([20, 20, 10]);
  translate([20, 0, 0]) cube([20, 20, 10]);
}

// FIX 2: overlap slightly
union() {
  cube([20.001, 20, 10]);
  translate([20, 0, 0]) cube([20, 20, 10]);
}
# Diagnosis
3dm info  # AI will often flag non-manifold geometry
# Also open the STL in your slicer and enable "Check for geometry errors"

C3 — Advanced Geometry: hull() and minkowski()

// hull() creates a convex envelope — useful for organic transitions
module smooth_transition() {
  hull() {
    translate([0, 0, 0])  cylinder(r=15, h=5, $fn=64);
    translate([0, 0, 30]) cylinder(r=5,  h=2, $fn=64);
  }
}
smooth_transition();

// minkowski() adds the secondary shape to every surface point
// Result: all edges rounded by 2 mm
module rounded_hull() {
  minkowski() {
    hull() {
      cylinder(r=10, h=3, $fn=8);           // octagonal prism
      translate([30, 0, 0]) sphere(r=8, $fn=32);
    }
    sphere(r=2, $fn=16);  // rounds all edges by 2 mm
  }
}
rounded_hull();

Quiz — Lesson 3dMake.10 (15 questions)

  1. What tool do you use to measure printed part dimensions against the design specification?
  2. What is tolerance stack-up, and why does it matter for multi-part assemblies?
  3. What causes non-manifold geometry in OpenSCAD, and how do you detect it?
  4. How does hull() differ from union()?
  5. What does 3dm info help you verify about your model?
  6. What is the diameter of a Cherry MX stem, and what clearance would you add for a slip-fit keycap?
  7. True or False: find -newer is an event-driven file change detection method.
  8. If three parts each have ±0.15 mm tolerance, what is the worst-case total error for a three-part stack?
  9. What does the $fn parameter control in OpenSCAD?
  10. Describe two methods for fixing non-manifold geometry caused by two touching (but not overlapping) shapes.
  11. What is the difference between hull() and minkowski() for creating organic shapes? Give one use case for each.
  12. What does resize([50, 0, 0]) do, and why might resize() behave unexpectedly for non-uniform scaling?
  13. When measuring a printed part with calipers25, what is the difference between an inside measurement and an outside measurement, and when does that distinction matter for tolerance analysis?
  14. Describe the iterative workflow for dialling in press-fit tolerances: what do you print, what do you measure, and how do you adjust?
  15. If 3dm info reports “the model appears non-manifold,” what are three possible causes you would investigate in your OpenSCAD code?

Extension Problems (15)

  1. Create a tolerance sensitivity study: build 5 keycaps with stem clearance from 0.05–0.25 mm in 0.05 mm increments, print them, and record which values fit your switches.
  2. Design a go/no-go gauge for a 10 mm nominal hole: a part with a “go” pin sized for slip-fit and a “no-go” pin sized for interference fit.
  3. Write a printer calibration SOP: bed levelling, first-layer calibration, and dimension verification. Include a measurement checklist.
  4. Build a three-tier stackable storage system for art supplies. Each tier has a different inner grid.
  5. Conduct a tolerance stack-up analysis for your stackable bin system. Calculate worst-case misalignment.
  6. Build a parametric test coupon that tests four wall thicknesses (0.8, 1.2, 1.6, 2.0 mm) in a single print.
  7. Design a caliper stand: a holder that keeps your digital calipers at a comfortable angle for one-handed operation.
  8. Build a non-manifold error catalogue: intentionally create 5 different types of non-manifold geometry, document how each was created, and how to fix it.
  9. Use hull() to design a smooth ergonomic tool handle and compare it to a simple cylinder handle.
  10. Create a printability checklist for new designs: overhangs, wall thickness, minimum feature size, support requirements. Apply it to your keycap and bin designs.
  11. Research the resize() function. Build an example showing how it behaves differently from scale() for non-uniform resizing.
  12. Design a multi-part assembly tutorial: a three-piece interlocking puzzle that teaches tolerance, alignment, and slip-fit.
  13. Build a “measurement worksheet” template in OpenSCAD: render a flat sheet that lists all key dimensions of a part as text, for printing alongside the part.
  14. Create a chi-squared goodness-of-fit test for your printer’s dimensional accuracy: measure 20 prints of the same part and determine whether the errors are normally distributed.
  15. Write a comprehensive troubleshooting guide covering the 10 most common 3D printing failures you have encountered or researched, with causes, prevention, and fixes.

References and Helpful Resources

  • OpenSCAD User Manual — Hull and Minkowski. https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Minkowski_and_Hull

Supplemental Resources

  • Programming with OpenSCAD EPUB Textbook — assets/Programming_with_OpenSCAD.epub
  • CodeSolutions Repository: https://github.com/ProgrammingWithOpenSCAD/CodeSolutions
  • OpenSCAD Quick Reference: https://programmingwithopenscad.github.io/quick-reference.html
  • All other reference documents are embedded as appendices below — no separate files needed.

Part 2: Reference Appendices

All supporting documents for Lesson 10 are included below. You do not need to open any additional files.


Appendix A: Measurement Worksheet

Use this for: Measuring real-world objects before modeling. Record three measurements per feature, then use the average in your OpenSCAD code — never a single measurement.

Student Name: ________________
Date: __________
Project / Assignment: ________________

How to Use This Worksheet

  1. Measure each feature three times and record all three values.
  2. Calculate the average: add the three values and divide by 3.
  3. Round to one decimal place (e.g., 23.4 mm).
  4. Use the average in your OpenSCAD code — not any single measurement.

Units: All measurements in millimeters (mm) unless otherwise noted.


Object 1

Object description: ________________

FeatureWhat You’re MeasuringM1 (mm)M2 (mm)M3 (mm)Average (mm)
Length (X)
Width (Y)
Height (Z)
Feature 4
Feature 5

Notes / sketches:

(describe the object here — label which direction is X, Y, Z)

Object 2

Object description: ________________

FeatureWhat You’re MeasuringM1 (mm)M2 (mm)M3 (mm)Average (mm)
Length (X)
Width (Y)
Height (Z)
Feature 4
Feature 5

Notes / sketches:

(describe the object here)

Object 3

Object description: ________________

FeatureWhat You’re MeasuringM1 (mm)M2 (mm)M3 (mm)Average (mm)
Length (X)
Width (Y)
Height (Z)
Feature 4
Feature 5

Object 4

Object description: ________________

FeatureWhat You’re MeasuringM1 (mm)M2 (mm)M3 (mm)Average (mm)
Length (X)
Width (Y)
Height (Z)
Feature 4
Feature 5

Object 5

Object description: ________________

FeatureWhat You’re MeasuringM1 (mm)M2 (mm)M3 (mm)Average (mm)
Length (X)
Width (Y)
Height (Z)
Feature 4
Feature 5

Accuracy Check

After completing all measurements, compare your averages with a partner who measured the same objects.

ObjectMy Average (mm)Partner’s Average (mm)Difference (mm)Within 1 mm?
1
2
3
4
5

If any difference is greater than 1 mm, remeasure together and find the source of the discrepancy.

Percent Error (Optional / Extension)

If your instructor provides the “true” dimension of an object, calculate your percent error:

% error = (|your average − true value| / true value) × 100

ObjectYour AverageTrue ValueDifference% Error

A percent error under 2% is excellent for caliper work at this level.

Reflection

Answer in complete sentences.

  1. Which measurement was most difficult to take and why?

  2. Did your three measurements for any feature vary significantly? What might cause that variation?

  3. If you were designing an object in OpenSCAD that needed to fit over one of these objects, which measurement would you use — your smallest, your largest, or your average? Why?


Appendix B: Measurement Calibration Guide

Ensure accurate dimensions in your printed parts through proper calibration and verification.

Why Calibration Matters

Printed dimensions often deviate from designed dimensions due to nozzle width variations, inconsistent extrusion flow rate, plastic shrinkage during cooling, slicer interpretation differences, and material-specific shrinkage (ABS can shrink 0.3–1%).

  • Typical tolerances without calibration: ±0.3–0.5 mm
  • Typical tolerances with calibration: ±0.1–0.2 mm

Pre-Print Calibration

1. Nozzle Diameter Verification

Print a simple 10 mm × 10 mm × 5 mm solid box at default 0.4 mm line width with 100% flow rate. Measure the result. If it deviates significantly from 10 mm, the nozzle may be partially clogged (clean it) or the wrong size (replace it).

2. E-Steps Calibration (Extrusion Rate)

E-steps control how many stepper-motor steps produce 1 mm of filament movement. If this is wrong, every print will be over- or under-extruded.

Method:

  1. Heat extruder to printing temperature.
  2. Mark filament 100 mm from the extruder entrance with a marker.
  3. Command extrusion of exactly 100 mm (G1 E100 F100).
  4. Measure the actual distance the mark moved.

Formula:

New E-steps = Current E-steps × (100 mm / Actual distance moved)

Example:
  Current: 93 steps/mm
  Commanded: 100 mm
  Actual moved: 92 mm
  New: 93 × (100 / 92) = 101 steps/mm

Apply with M92 E101 then M500 to save (Marlin), or update configuration file (Klipper).

3. First Layer Height Verification

Print a single-layer square (base layer only). The first layer should be 0.2–0.25 mm thick — roughly the thickness of a standard piece of printer paper. Adjust Z-offset by ±0.05 mm increments until correct.


XY Dimension Calibration

Test file (OpenSCAD):

cube_size      = 20;
wall_thickness = 2;

difference() {
  cube([cube_size, cube_size, cube_size], center=true);
  cube([cube_size - 2*wall_thickness,
        cube_size - 2*wall_thickness,
        cube_size + 1], center=true);  // open top
}

Print at 100% flow rate. Allow complete cooling (2+ hours). Measure the internal dimension at 3 locations per axis. Expected internal width: 20 - 2×2 = 16 mm.

Calibration formula:

Flow rate adjustment = (Expected internal / Actual internal) × 100%

Example:
  Expected: 16.00 mm
  Actual: 15.75 mm
  Adjustment: (16.00 / 15.75) × 100% = 101.6%  →  set flow to 101.6% in slicer

Shrinkage Compensation by Material

MaterialTypical ShrinkageRecommended Action
PLA0.3–0.5%Usually acceptable; no action needed
PETG0.5–1%Scale design up 0.5–1% for critical dimensions
ABS0.8–1.5%Scale up 1% minimum
TPU1–2%Scale up 1–2% for critical dimensions

Apply in OpenSCAD:

final_size        = 20;
material_shrink   = 1.01;  // 1% for ABS
designed_size     = final_size * material_shrink;

Critical Measurements to Track

MeasurementMethodAcceptable ToleranceFrequency
Wall thicknessCalipers (3 spots)±0.1 mmEvery print
Hole diameterCalipers or gauge±0.1–0.2 mmEvery print
Overall dimensionsCalipers±0.2 mmMonthly
Layer heightStack on calipers±0.02 mmMonthly
Vertical heightMeasure side face±0.1 mmEvery print

Quick Calibration Checklist

Before first print with new settings:

  • E-steps calibration complete
  • First layer height verified
  • Nozzle diameter confirmed
  • Test print completed and measured

Monthly maintenance:

  • Calibration cube printed and measured
  • Flow rate adjusted if needed
  • Layer height verified
  • Temperature consistency checked

After any hardware change (nozzle swap, bed relevel, material change):

  • Re-verify nozzle diameter
  • Re-verify first layer height
  • Test print and measure before production prints

ToolTypical CostAccuracyBest Use
Digital calipers$5–15±0.05 mmPrimary tool for all work
Steel ruler$3–10±1 mmQuick rough checks
Vernier calipers$10–30±0.05 mmPrecision work
Micrometer$20–50±0.01 mmCritical tolerance verification

Recommendation: Digital calipers are the most versatile and affordable starting point. Buy a pair before you print your first functional part.


Calibration Record

FieldValue
Last Calibration Date
Printer Model
Current E-Steps
Current Flow Rate
Materials Calibrated For

Appendix C: Diagnostic Checklist

Use this checklist to systematically diagnose and troubleshoot printing issues before consulting the solutions guide.

Quick Diagnosis Flowchart

Print Problem?
|
+---- [Before Print] Issues?
|  +---- Filament won't load  ->  CHECK: Temperature, drive gear, nozzle
|  +---- Printer won't heat   ->  CHECK: Power, temp sensor, firmware
|  +---- Bed not level        ->  CHECK: Leveling routine, bed surface
|
+---- [First Layer] Issues?
|  +---- Won't stick          ->  CHECK: Bed temp, cleanliness, nozzle height
|  +---- Too squished         ->  CHECK: Nozzle height, bed temp
|  +---- Gaps / uneven        ->  CHECK: Bed levelness, hot end alignment
|
+---- [Mid-Print] Issues?
|  +---- Stops extruding      ->  CHECK: Clog, temp drop, jam
|  +---- Layers shift         ->  CHECK: Loose belts, mechanical bind
|  +---- Print wobbles        ->  CHECK: Build plate, print stability
|
+---- [Print Quality] Issues?
   +---- Weak / brittle       ->  CHECK: Temperature, flow rate, layer adhesion
   +---- Rough surface        ->  CHECK: Flow rate, speed, temperature
   +---- Warped               ->  CHECK: Bed temperature, cooling, material

Pre-Print Diagnostics

A — Power and Connectivity

  • Printer powered on; LED indicators normal
  • No error codes displayed; interface responding
  • USB connected (if applicable)

If failed: check power outlet, cable, power supply specs; power-cycle (off 30 sec, back on).

B — Temperature System

Heat hot end to 200°C; time to reach temperature should be 2–4 minutes with a steady rise (no plateau). Heat bed to 60°C; should reach target in 5–10 minutes.

Stability test: After reaching target, record temperature every minute for 10 minutes.

RangeAssessment
±2°CExcellent
±5°CAcceptable
±10°CMarginal — investigate thermal sensor
>±10°CProblem — do not print until resolved

C — Mechanical Systems

Disable motors (if firmware allows) and manually move each axis. Expected: smooth, no grinding.

AxisResult
X-axissmooth / rough / stuck
Y-axissmooth / rough / stuck
Z-axissmooth / rough / stuck

If rough or stuck: check for visible obstructions, inspect rails, verify pulleys turn freely, check belt tension, lubricate dry joints.

D — Build Plate Leveling (Paper Method)

  1. Heat bed and nozzle to printing temperature.
  2. Move nozzle to each corner; adjust leveling screw until a standard sheet of paper drags slightly under the nozzle.
  3. Repeat for all 4 corners, then check center.
  4. Target: consistent slight paper drag at all points; nozzle does not contact bed anywhere.

E — Filament and Extruder

  • Filament diameter visually consistent over ~50 cm
  • No visible cracks, kinks, or damage
  • Spool rotates freely without binding
  • Filament path clear of obstructions

Manual extrusion test: Heat to printing temperature. Push 10–20 mm of filament through manually. Expected: smooth push, consistent flow at nozzle tip.


First Layer Appearance Guide

AppearanceCauseFix
Wavy / embossed linesNozzle too close to bedRaise Z-offset
Gaps between linesNozzle too far from bedLower Z-offset
Completely squished flatNozzle too low or bed too highRaise Z-offset or re-level
Partial adhesion onlyBed too cool or dirtyClean bed; increase bed temperature
Consistent, even linesCorrectContinue print

Mid-Print Extrusion Failure

When extrusion stops during a print:

  1. Pause (do not cancel) immediately.
  2. Listen for extruder grinding sounds (indicates jam).
  3. Observe whether filament is still feeding into the extruder.
Is filament stuck in the extruder?
+---- YES  -->  Nozzle clog likely
|               Try: cold pull, retract, then clean nozzle
|               See Appendix D (Common Issues) for full procedure
|
+---- NO   -->  Loading/path issue
               Is spool binding?     -->  Fix spool rotation
               Is path blocked?      -->  Clear obstruction
               Is drive gear slipping? -->  Clean and re-tension drive gear

Dimensional Accuracy Check (After Print Cools)

Let the print cool for at least 2 hours before measuring.

Measurement protocol:

  1. Measure each dimension 3 times at different locations.
  2. Calculate average.
  3. Compare to the design dimension.
  4. Calculate deviation: Deviation % = ((Measured − Design) / Design) × 100%
ToleranceStatusAction
±0.5 mm or betterPASSNo adjustment needed
±0.5–1 mmMARGINALDocument and monitor
>±1 mmFAILAdjust flow rate or recalibrate

Diagnostic Report Template

Fill this out before seeking help — it ensures you’ve systematically checked the most common causes.

DIAGNOSTIC REPORT
=================
Printer Model:
Problem Description:
When it occurs: (always / sometimes / first 5 layers / etc.)
Recent changes (nozzle swap, new filament, new settings):

DIAGNOSTICS PERFORMED:
[ ] Power / connectivity verified
[ ] Temperatures verified and stable
[ ] Mechanical movement tested on all axes
[ ] Bed leveling checked
[ ] Filament loading tested
[ ] First layer inspected and evaluated
[ ] Print quality evaluated mid-print

Key Findings:
1.
2.
3.

Attempted Solutions:
1.
2.

Result: (Solved / Partial / Ongoing)

Appendix D: Common Issues and Solutions

Comprehensive troubleshooting guide for the most frequent 3D printing problems. Cross-reference with the Diagnostic Checklist (Appendix C) to identify which section applies to your situation.


Pre-Print Issues

Problem: Filament Won’t Load

Symptoms: Extruder clicks or grinds but no filament moves; nothing extrudes when manual extrude is commanded.

Diagnosis checklist:

  • Nozzle temperature high enough for the material?
  • Filament path clear of obstructions?
  • Drive gear still has grip (not worn smooth)?
  • Extruder tension set correctly?

Solutions (try in order):

  1. Increase nozzle temperature by 10°C — too cold makes extrusion harder.
  2. Clean the extruder drive gear with a wire brush to restore grip.
  3. Check filament diameter — should be 1.75 mm ±0.03 mm. A spool that measured correctly when new may have inconsistent sections.
  4. Verify extruder tension — should grip firmly but not crush the filament.
  5. Inspect nozzle for partial clog (see “Nozzle Clog” below).

Problem: Warped or Damaged Filament

Symptoms: Filament appears kinked on the spool; inconsistent diameter; melted spots.

Solutions:

  1. Cut off ~30 cm of the damaged section and discard.
  2. If the filament seems brittle or stringy: dry it in a low oven at 50°C for 2 hours (PLA). Moisture absorption causes significantly worse print quality.
  3. Store filament sealed with desiccant between sessions — especially important for Nylon, PETG, and TPU, which are hygroscopic.

Problem: Poor Bed Adhesion (First Layer Lifts)

Symptoms: Print lifts off bed during printing; edges curl up; print comes free entirely.

Solutions (most effective first):

  1. Re-level the build plate — cold plate leveling is more accurate.
  2. Clean the build plate — wipe with isopropyl alcohol to remove oils and dust.
  3. Lower the nozzle — if it’s too high, reduce Z-offset by 0.05–0.1 mm.
  4. Increase bed temperature by 5–10°C.
  5. Material-specific adhesion aids:
    • PLA: Painter’s tape, glue stick, or clean bare PEI/glass
    • PETG: Textured PEI or thin glue layer (prevents it from bonding too strongly to smooth surfaces)
    • ABS: Heated enclosure + blue tape + ABS slurry (acetone + scraps)
    • TPU: Clean bed, slightly elevated temperature

Problem: Nozzle Clog

Symptoms: No extrusion after initial layers; consistent gap between nozzle and surface; clicking from extruder; pressure building in hot end.

Solutions (increasing intensity — try each before escalating):

  1. Cold Pull: Heat nozzle to 200°C, grip filament, pull firmly while the nozzle cools. Repeat 5–10 times. The extracted filament should have a “plug” shape that brought debris with it.

  2. Poke from top: Heat to printing temperature. Carefully insert a 0.3–0.4 mm drill bit or acupuncture needle through the top of the nozzle (from the heatbreak side). Do not force — the goal is to break up, not compact, the clog.

  3. Soak and clean: Remove the nozzle while hot (use wrench). Soak in acetone for 20–30 minutes. Use an ultrasonic cleaner if available. Clear the passage with a thin needle.

  4. Replace: If the clog persists, the nozzle may be damaged internally. Replacement nozzles cost $3–10 — keep spares on hand.

Problem: Under-Extrusion (Thin Walls, Weak Prints)

Symptoms: Walls thinner than expected; layers separate easily; visible horizontal gaps; sections that appear lighter in color.

Solutions:

  1. Check for partial nozzle clog (a fully extruding nozzle means a partial clog is possible).
  2. Increase flow rate by 5–10% in the slicer.
  3. Raise temperature by 5–10°C.
  4. Reduce print speed by 10–20%.
  5. Calibrate E-steps (see Appendix B).
  6. Clean drive gear to remove accumulated plastic dust.

Problem: Over-Extrusion (Blobs, Rough Texture)

Symptoms: Excess material squishing between layers; rough, bumpy surface; blobs or zits on walls.

Solutions:

  1. Reduce flow rate to 95% in the slicer.
  2. Lower temperature by 5–10°C.
  3. Verify line width — should be approximately 1.2× the nozzle diameter (0.4 mm nozzle → 0.48 mm line width).
  4. Check slicer settings for nozzle size — ensure it matches the actual nozzle installed.

Problem: Layer Shifting

Symptoms: Layers offset horizontally mid-print; top portion of print is misaligned; usually occurs at a specific layer height.

Solutions:

  1. Check mechanics: manually move X/Y (motors disabled) — should feel smooth, no resistance. Tighten all visible screws. Inspect belts for fraying.
  2. Reduce travel speed by 20–30%. Reduce acceleration in firmware.
  3. Check print orientation — tall, thin prints are vulnerable to the nozzle catching an edge and shifting. Rotate or add a brim.
  4. If recently updated firmware: verify acceleration settings (try 1000 mm/s²) and step/mm calibration.

Problem: Stringing (Fine Threads Between Parts)

Cause: Nozzle oozes molten filament while traveling between print sections.

Solutions:

  1. Reduce temperature by 5–10°C.
  2. Increase retraction distance by 0.5–1.5 mm.
  3. Increase retraction speed.
  4. Enable “wipe on retract” in slicer.
  5. Check for worn nozzle — worn nozzles ooze more than new ones.

Problem: Warping (Corners Curl Up)

Cause: Material cools unevenly and contracts at different rates across the print.

By material:

  • ABS: Use a heated enclosure, slow cooling fan, higher bed temperature (100–110°C).
  • PETG: Reduce cooling fan speed; increase bed temperature.
  • PLA: Usually warps if bed temperature is too high — reduce it.

Maintenance to Prevent Issues

IssuePreventionFrequency
ClogsClean nozzle; avoid heat-creep by maintaining cooling fanBefore each print
Bed adhesionLevel bed; clean plate with IPABefore each print
Layer shiftCheck belt tension and drive gear screwsMonthly
Inconsistent qualityCalibrate E-steps; standardize environmentQuarterly
Worn nozzleMonitor extrusion quality; replace on scheduleEvery 6 months
Moisture in filamentStore sealed with desiccantOngoing

Appendix E: Accessibility Audit — Extension Project

Estimated time: 2–4 hours. This is an optional extension project for students who want to go deeper into inclusive design.

Overview

Accessibility means designing tools, documents, and workflows so that people with different abilities — including visual impairment, motor differences, and cognitive differences — can use them fully. In a fabrication context, accessibility applies to both the physical products you design and the documentation you produce about them.

This extension project asks you to evaluate one lesson or project for non-visual accessibility barriers, implement concrete improvements, and document what you found.

Learning Objectives

By completing this project, you will:

  • Evaluate digital content for accessibility barriers related to vision, blindness, and low vision
  • Apply concrete accessibility best practices (alt-text, code comments, plain language)
  • Document improvements and estimate implementation effort
  • Strengthen your awareness of inclusive design as a professional responsibility

Tasks

  1. Select one lesson or project (an OpenSCAD file plus its markdown instructions) and review it for accessibility shortcomings.
  2. Create a checklist covering: image alt-text, code walkthroughs, tactile cues, plain-language explanations, and file naming conventions. Apply it to the chosen resource.
  3. Implement at least three small improvements (add alt text, improve code comments, write a text-only step-by-step walkthrough) and document every change.
  4. Produce a one-page audit report summarizing what you found, what you fixed, and what larger improvements would require instructor time.

Deliverable

A one-page audit report plus a documented set of proposed changes (a “patch” or diff) for the target lesson.

Accessibility Principles to Apply

Alt-text for images: Every image in a document should have a written description that conveys the same information. For a diagram showing a cross-section, the alt-text describes what the cross-section shows, not just “diagram.”

Code walkthroughs: OpenSCAD files should include a plain-English comment block at the top describing what the file does and how to navigate it. Each module should have a comment explaining its purpose and parameters in plain language.

Tactile cues in designs: When designing objects that will be used physically, consider how they work for people who navigate by touch. Distinct ridges, chamfered corners, and different textures at key locations all improve usability for visually impaired users.

Plain language: Avoid jargon where a simpler word works. When technical terms are necessary, define them on first use.


Student Audit Documentation Template

Author: ________
Date: ________
Lesson/Project Audited: ________

Audit Scope

Resources reviewed:

Testing methodology used (screen reader, keyboard-only navigation, checklist review, other):


Detailed Findings

For each resource reviewed, complete the following:

Resource 1: ________

Screen reader assessment:

  • Navigation: clear / unclear / broken
  • Output readability: readable / partially readable / unreadable
  • Error messages: helpful / unclear / missing
  • Specific barriers found:

Keyboard navigation:

  • All functions accessible via keyboard: Yes / No
  • Tab order logical: Yes / No
  • Specific barriers:
RecommendationPriority (H/M/L)Feasibility (Easy/Med/Hard)Impact (H/M/L)

(Repeat for each resource)


Summary of Barriers Found

BarrierFrequencySeverityResources Affected

Recommendations Matrix

PriorityFeasibilityImpactRecommendationImplementation Steps
HighEasyHigh
HighMediumHigh
MediumEasyMedium

Reflection Questions

Answer in complete sentences:

  1. What surprised you about the accessibility barriers you found?
  2. How would you prioritize improvements if you had limited time?
  3. What role should users with disabilities play in accessibility testing, rather than non-disabled designers guessing at barriers?
  4. What would it take to make accessibility review a standard part of the lesson development process?

Action Plan

  • Which improvements will you tackle first, and why?
  • How will you verify that your improvements actually help?
  • Timeline for implementation:

Assessment (if graded)

CategoryScore (0–3)Notes
Problem & Solution — barriers identified, improvements actionable
Design & Code Quality — testing methodology rigorous, findings specific
Documentation — template complete, recommendations prioritized
Total (0–9)
-e

Lesson 11 — Stakeholder-Centric Design and the Final Project

Course: 3dMake Certification — Leadership Level Estimated Time: 3–6 weeks (iterative; worked in phases)


A Message to You Before We Begin

You have spent this course mastering the how of digital fabrication: coding geometric primitives, managing tolerances, automating builds. This final lesson focuses on the why. A professional designer does not simply build what they want — they build what a stakeholder needs.

This lesson bridges the gap between being a maker and being a design professional. It introduces Design Thinking and Requirement Engineering, then puts those tools to work in a sustained final project you will carry through from a single conversation with a real person all the way to a finished, documented, physical artifact.

The goal is not perfection on the first try. The goal is to experience the full design cycle — the same cycle that professional product designers, engineers, and makers go through when creating physical products. You will make decisions, encounter problems, revise your approach, and end up with something better than you could have imagined at the start.


Learning Objectives

By the end of this lesson and project, you will be able to:

  • Conduct a structured stakeholder interview using open-ended questioning strategies
  • Extract Functional Requirements and define measurable Acceptance Criteria from user data
  • Translate human needs into a Technical Design Specification
  • Build a fully parametric assembly in OpenSCAD that solves a specific user problem
  • Iterate a design based on systematic feedback collection
  • Demonstrate mastery of all prior curriculum concepts in a single integrated project

Part 1: Concepts — Stakeholder-Centric Design

What “Stakeholder-Centric” Means

In engineering, a stakeholder is anyone affected by your design. This includes the person who asked for it, the person who will use it, the person who maintains it, and anyone who lives near it or depends on it. Professional designers do not start with shapes — they start with people.

The shift from “maker” to “design professional” is exactly this: a maker builds what they find interesting. A design professional builds what the stakeholder actually needs, which is often different.

This is harder than it sounds. People are not always able to articulate what they need. They describe symptoms, not root causes. They say “it needs to be bigger” when what they mean is “it’s too hard to grab with one hand.” Your job is to ask the right questions, listen carefully, and translate what you hear into design constraints.

The Design Loop for Professionals

Design Thinking is a structured method for solving problems that begins with understanding humans, not geometry. The five-stage loop is:

  1. Empathize — Interview the user to understand their “pain points.” What do they struggle with? What workarounds do they currently use?
  2. Define — Create a list of requirements the part must satisfy. Make them specific and testable.
  3. Ideate — Use your OpenSCAD skills to create a parametric solution that addresses the requirements.
  4. Prototype & Test — Build the part and have the stakeholder test it with their own hands.
  5. Iterate — Refine the parameters based on their feedback. Go back to step 1 if the problem changed.

An important point: this is not a linear process. You will frequently loop back. You might build a prototype only to discover during testing that you defined the wrong problem. That is not a failure — that is the process working correctly. The goal is to discover that early, while revisions are cheap.


Concept 2: The Stakeholder Interview

You cannot design for someone you don’t understand. A stakeholder interview is a structured conversation, not a quick survey. Done well, it reveals needs the user didn’t know how to express on their own.

Strategy: Open-Ended Questions

The single most important skill in an interview is asking questions that cannot be answered with “yes” or “no.”

Compare these two approaches:

Closed QuestionOpen-Ended Alternative
“Do you want it to be 10 cm wide?”“How would you use this in your daily space?”
“Is it too heavy?”“Tell me about a time you had trouble using something like this.”
“Should it be red?”“What does the space where this will live look like?”

The open-ended version invites the user to tell you things you didn’t know to ask about. The closed version only confirms or denies what you already assumed.

What to Listen For

As the user talks, you’re listening for three categories of constraint:

  • Physical constraints: “It needs to fit on my nightstand.” “I only have 15 cm of clearance on the shelf.”
  • Accessibility constraints: “I need to find the beads by touch alone.” “My hands shake, so I need large controls.”
  • Durability/use constraints: “I tend to drop things — it can’t be fragile.” “My kids will try to pull it apart.”

Write down exact quotes. The user’s own words often contain the most precise requirements.


Concept 3: Engineering Functional Requirements

After the interview, you have a set of notes full of observations, stories, and opinions. Before writing any code, you must translate that material into Functional Requirements (FRs) — specific, testable statements of what the design must do.

The “User Story” Pattern

Use this format for every requirement:

“As a [user type], I want to [action] so that [benefit].”

This structure forces you to keep the user’s perspective central. Examples:

  • “As a jewelry collector, I want the holder to have 2 mm clearance so that my bracelets slide on easily but don’t fall off.”
  • “As an elderly user, I want the clasp to require only one hand to operate so that I can put it on independently.”
  • “As a person with low vision, I want distinct tactile ridges on each section so that I can identify compartments without looking.”

Acceptance Criteria

Once you have a requirement, you need a test for it — a specific condition that, when met, proves the requirement is satisfied. Without acceptance criteria, you can never know if you’re done.

Functional RequirementAcceptance Criterion
Must support weight without tippingHolds 200 g with center of gravity at the rim; does not tip on a 5° incline
Bead hole accommodates 1.5 mm cordA 1.5 mm test cord passes through with finger pressure; does not fall out under its own weight
No sharp edgesA flat palm pressed across all surfaces for 5 seconds produces no discomfort or marks

Concept 4: Technical Design Specification

A Technical Design Specification is the bridge between requirements and code. It maps each FR to a named OpenSCAD parameter, defines the calculation behind each dimension, and records the reasoning.

This document is not bureaucracy. It is a record of decisions. When you revisit a design three weeks later and wonder “why did I make the base this wide?”, the specification has the answer.

Code Pattern: Requirement Mapping

Variable names in your code should reflect the requirement they satisfy. Anyone reading the code should be able to trace a variable back to the FR that motivated it.

// FR1: Must fit standard bracelet diameters (typically 50–70 mm)
bracelet_max_d = 70;

// FR2: Must be stable without external support.
// Calculation: base width = 1.2 × total height (stability ratio)
base_w = 1.2 * total_height;

// FR3: Accessibility. Add tactile ridges for orientation by touch.
module tactile_marker() {
  sphere(r=2, $fn=16);
}

When a reviewer reads this code, they see not just what you built, but why. That’s the mark of professional-level documentation.


Concept 5: Feedback and Iteration

After your first print, the work is not done — it has just shifted. You move from designing to testing, and the user’s hands are your most important instrument.

Structured Feedback Collection

Don’t just ask “what do you think?” That produces vague answers. Instead, observe the user using the object before asking any questions. Watch for:

  • Hesitation (something isn’t intuitive)
  • Workarounds (they’re compensating for a flaw)
  • Surprise (positive or negative — both are signals)

Then ask specific questions: “Was it easy to open with one hand?” “Did any part feel rough or uncomfortable?” “Is there anything you’d want to be different?”

The Refinement Rule

Never guess at a fix based on vague feedback. If the user says “it’s too tight,” measure the actual fit with calipers before changing anything. Calculate the required clearance. Update your TOLERANCE constant. Print a test coupon before printing the full part.

This is the difference between engineering and guessing. Engineering produces predictable results. Guessing produces random results that occasionally work.


Part 2: The Project

You have two options for your final project. Both use the Design Thinking framework above. Your instructor will specify which option applies to your cohort.


Option A: The Beaded Jewelry Project

Unit: 3 — Open-Ended Projects Estimated Duration: 1 week

Project Brief

Design and produce a wearable beaded jewelry piece that includes at least eight 3D-printed beads generated in OpenSCAD. Your design must use two distinct parametric bead modules and combine them into a completed, wearable piece (necklace, bracelet, or similar).

The jewelry project is an accessible entry point into stakeholder-centric design: the “stakeholder” is a real person (yourself, a friend, or a family member) with specific aesthetic preferences and physical requirements, and the “product” must be safe to wear, comfortable, and actually assembled.

Constraints (must follow)

  • Your prototype must include a 3D-printed component designed in OpenSCAD.
  • Code your project in a single .scad file that parameterizes bead shapes for repeatability.
  • Use at least two different bead shapes in the final assembly.
  • The final piece must be wearable and assembled — not just a set of loose beads.

Learning Objectives

  • Create parametric OpenSCAD modules for repeated geometry
  • Combine modular parts into a coherent assembled object
  • Document design decisions and printing notes for reproducibility
  • Evaluate designs against measurable functional requirements

Step-by-Step Milestones

Day 1 — Project Setup

  • Read this briefing and complete your Stakeholder Interview (use the template in Part 3 of this document).
  • Create a project folder. Initialize your Design Notes document.
  • Define at least 3 Functional Requirements using the FR template in Part 3.

Days 1–2 — Bead Module Development

  • Implement bead_A(size, detail) and bead_B(size, detail) parametric modules.
  • Your modules must accept at least two parameters: a size parameter and a detail/resolution parameter.
  • Test-print a single bead from each module. Record optimal print temperature and bed settings.

Here is a minimal starting scaffold — replace the geometry with your own design:

// ============================================================
// Beaded Jewelry — Main Source File
// Author: [Your Name]
// Date: [YYYY-MM-DD]
// ============================================================

// ---- Key Parameters (change these to adapt the design) ----
bead_size    = 12;    // mm — controls overall bead scale
detail       = 32;    // $fn equivalent — increase for smoother curves
hole_d       = 2.8;   // mm — cord hole diameter (measure your cord + 0.3 mm clearance)
clearance    = 0.3;   // mm — added to hole for reliable cord passage

// ---- Bead A: Round/Sphere Variant ----
module bead_A(size=bead_size, fn=detail) {
  difference() {
    sphere(r=size/2, $fn=fn);
    // Cord hole through center
    translate([0, 0, -(size/2 + 0.001)])
      cylinder(r=(hole_d + clearance)/2, h=size + 0.002, $fn=16);
  }
}

// ---- Bead B: Bicone/Diamond Variant ----
module bead_B(size=bead_size, fn=detail) {
  difference() {
    // Bicone: hull of two cones meeting at midpoint
    hull() {
      translate([0, 0, size/4])  cylinder(r=size/2, h=0.1, $fn=fn, center=true);
      translate([0, 0, -size/2]) cylinder(r=0.1,    h=0.1, $fn=fn, center=true);
      translate([0, 0,  size/2]) cylinder(r=0.1,    h=0.1, $fn=fn, center=true);
    }
    // Cord hole
    translate([0, 0, -(size/2 + 0.001)])
      cylinder(r=(hole_d + clearance)/2, h=size + 0.002, $fn=16);
  }
}

// ---- Assembly: arrange 8+ beads in a line for spacing test ----
// Comment/uncomment individual modules to render one at a time for export

spacing = bead_size * 1.1;  // 10% gap between beads

for (i = [0:7]) {
  translate([i * spacing, 0, 0])
    if (i % 2 == 0) bead_A();
    else            bead_B();
}

Days 3–4 — Assembly and Iteration

  • Create an assembly that arranges at least 8 beads and tests fit and tolerances.
  • Print and string the beads on your chosen cord.
  • Iterate hole diameter and spacing until beads slide freely but do not fall off.
  • Record every iteration in your revision log.

Day 5 — Final Prototype and Documentation

  • Print the final bead set. Assemble the complete piece.
  • Photograph the result (multiple views, at least one worn).
  • Complete all deliverables listed below.

Deliverables

Submit both digitally and physically as instructed:

  • .scad file containing parametric bead modules and the assembly script
  • .stl files (exported as needed) for printed parts
  • Technical documentation including:
    • Design Notes (ideas, measurements, parameter values, revision log)
    • Construction / 3D printing notes (temperatures, speeds, supports, any failures)
    • Completed Stakeholder Interview (Part 3 of this document)
    • Completed Functional Requirements (Part 3)
    • Photos of final prototype (multiple views)
  • Physical turn-in: one assembled piece (if required by instructor)

Functional Requirements (examples — adapt to your design)

  • The bead module must allow a hole diameter adjustable in 0.1 mm increments between 2.0–4.0 mm.
  • The assembly must include at least 8 beads and remain wearable (fits comfortably on intended body part).
  • The OpenSCAD file must be parameterized such that changing a single scale parameter adjusts bead size consistently.
  • The assembled piece must not have sharp edges that would injure skin under normal use.

Accessibility Note

Provide alt-text for all photos in your documentation. Include a short written walkthrough of how your .scad file generates the bead shapes so screen-reader users can understand the sequence and parameters.

Grading Rubric — Option A (0–9 scale)

See the Master Rubric in Part 3 of this document for the full scoring framework. For Option A:

CategoryMax PointsWhat Is Evaluated
Implementation & parametric code3Modules are parametric, well-named, commented; assembly uses variables
Functionality & wearability3Piece is wearable; holes fit cord; no sharp edges; FRs met
Documentation & print notes2Design notes, revision log, FR document, print settings recorded
Presentation & photos1Multiple views; worn photo; alt-text provided

Quiz — Option A: Beaded Jewelry (15 questions)

  1. Why use parametric modules for repeated parts rather than copying geometry? (one sentence)
  2. What is a reliable way to test a bead hole size for a given cord diameter before printing the full set?
  3. Name two OpenSCAD features or techniques useful for repeating geometry across a pattern.
  4. What print setting is most likely to affect hole diameter accuracy in FDM printing?
  5. How would you document an iteration that changed hole diameter from 2.5 mm to 2.7 mm?
  6. True or False: Once your first bead prints successfully, all subsequent iterations will print exactly the same.
  7. Explain what “wearability” means for a jewelry design. Name two specific checks you would perform to confirm a necklace is comfortable.
  8. Your bead design uses a 3 mm hole. When strung on cord, it’s too tight to slide. What are two OpenSCAD-level solutions?
  9. When documenting your design for reproducibility, should you record (A) final bead dimensions only, (B) all iterations including failed attempts, or (C) just the most recent version?
  10. Why does the Stakeholder Interview happen before you write any code?
  11. Write a User Story for the following requirement: the cord hole must accommodate a 1.5 mm nylon cord.
  12. What is an Acceptance Criterion, and how does it differ from a Functional Requirement?
  13. You receive feedback that the beads “feel scratchy.” Describe the engineering process for investigating and fixing this — do not just say “sand them.”
  14. What is the hull() function useful for in bead design? Give one specific example.
  15. Describe how the Design Loop (Empathize → Define → Ideate → Prototype → Iterate) applied to your specific jewelry project. Reference at least one concrete decision you made at each stage.

Extension Problems — Option A (15)

  1. Design an interlocking bead (snap-fit connection between beads) and document the clearances required.
  2. Create a parametric clasp module that integrates with your bead string and includes a documented pass/fail test.
  3. Modify one bead to include decorative text or a pattern generated procedurally in OpenSCAD.
  4. Convert your single .scad project into a small library: separate bead modules into use-able include files and demonstrate reuse.
  5. Propose a modification to make the piece weather-resistant for outdoor wear (materials, coatings, or geometry changes). Justify each choice.
  6. Design and print a complete jewelry set: matching beads, clasp, and string connector with a consistent design language.
  7. Create a variant generator that produces 10+ different bead designs from single-parameter changes. Document aesthetic and functional differences.
  8. Build a design system document for your jewelry: modular bead library, material requirements, assembly instructions, and care guide.
  9. Investigate material effects: print the same bead in two or more materials. Compare durability, aesthetics, and wearability with measurements.
  10. Develop a parametric customization guide: enable another person to modify size, spacing, and aesthetics through top-level variables alone.
  11. Conduct a tolerance sensitivity study: print 5 versions of a bead hole from 2.5 mm to 3.5 mm in 0.25 mm increments. Record which passes, which fails, and why.
  12. Design a “tolerance coupon” — a single flat print that tests 4 different hole diameters simultaneously — so you can calibrate your printer for bead work in one print.
  13. Use surface() or minkowski() to add a texture to your bead surface. Document the performance impact and the $preview guard you used.
  14. Write a batch build script that exports STLs for 8 bead variants (different sizes or shapes) automatically, with timestamped output names.
  15. Conduct a formal stakeholder feedback session using the Feedback Collection Template (Part 3). Document the changes you made as a result.

Option B: Open-Ended Final Project

Estimated Duration: 3–6 weeks

Project Brief

Design, build, test, iterate, and document a real functional 3D-printed product of your choosing. This is not a tutorial — there are no step-by-step instructions, no starter code, no single correct answer. You choose the problem; you design the solution; you prove it works.

What Makes a Good Project?

Functional: It does something real. Not a demonstration object — an actual thing that solves a problem or serves a purpose.

Multi-part: At least two printed components that must fit together. This forces you to engage with tolerances, alignment, and interlocking features.

Parametric: Defined by variables, not hardcoded geometry. Someone else should be able to adapt your design to a different size or use case by changing a few numbers.

Printable: All components can be printed on a standard FDM printer without exotic supports or materials.

Original: Designed by you from scratch. You may be inspired by existing designs, but the code must be yours.

Suggested Project Categories

Category A: Organizer / Storage — A system for organizing a specific collection of physical objects. Examples: parametric desktop organizer with interlocking cells; tool wall panel with snap-on holders; cable management clips sized for real cable diameters. Why it works: real measurements to take, natural parametric axis, tolerance requirements throughout.

Category B: Mounting / Enclosure — A mount, bracket, or enclosure for a specific real-world object. Examples: Raspberry Pi enclosure with lid and vent pattern; custom camera mount for a specific model; weatherproof sensor housing. Why it works: must fit real hardware, heat-set insert practice, printability constraints.

Category C: Ergonomic Tool or Accessory — Something designed to be held, worn, or operated. Examples: custom stylus grip, thumb ring for archery, ergonomic handle with grip texture. Why it works: forces hull() for organic shapes, material selection for comfort, iterative refinement by feel.

Category D: Mechanical Mechanism — A mechanism with moving parts. Examples: living hinge box, adjustable ratcheting stand, pen plotter stage. Why it works: most demanding tolerances, deep engagement with clearance and snap-fit mechanics.

Category E: Educational / Demonstrative Object — A physical object that teaches a concept. Examples: parametric gear train, manifold geometry demonstration set, printer calibration kit. Why it works: strong parametric requirements, mathematical derivation in code, natural documentation need.


Project Phases (Option B)

The project is organized into four phases. Work through them sequentially — do not skip ahead.


Phase 1: Define and Plan (Week 1)

Goal: Understand the problem before writing any code.

The most common mistake in design projects is rushing to CAD. Phase 1 forces you to think before you model.

Phase 1 Deliverables

1.1 — Stakeholder Interview Conduct a 45-minute interview using the Stakeholder Interview Template (Part 3). Your stakeholder is a real person who will use or benefit from your design.

1.2 — Problem Statement (200–400 words) Answer in prose: What specific problem does your design solve? Who will use it, and when? What must it do to be considered successful? What are the key constraints?

Do not describe the geometry yet. Describe the need.

1.3 — Measurement Worksheet Before modeling, measure everything relevant in the real world with digital calipers.

DimensionDescriptionNominal (mm)Measured (mm)Tolerance
±…

Measure at least 10 dimensions. For enclosures, measure the enclosed object completely. For mechanisms, measure all hardware that must interface with printed parts.

1.4 — Functional Requirements Use the FR Template (Part 3) to write at least 3 Functional Requirements, each with a User Story and at least one Acceptance Criterion.

1.5 — Design Specification Use the Design Specification Template (Part 3) to map your FRs to named OpenSCAD parameters.

1.6 — Sketch / Block Diagram Draw your design by hand (or any drawing tool). Label all key dimensions. Identify every interface between parts.

1.7 — Preliminary Bill of Materials

PartMaterialEst. print timeEst. filament (g)Qty

Include both printed and non-printed components.

1.8 — Risk Assessment Identify three design challenges you anticipate. For each: what could go wrong, which tolerances are critical, and how will you address the risk.


Phase 2: Prototype and Test (Weeks 2–3)

Goal: Build a working first version. Find the problems.

A prototype is a physical question: “Does this work?” Print fast, test aggressively, find the failure modes.

Phase 2 Deliverables

2.1 — Parametric Source File

// ============================================================
// [Project Name] — Main Source File
// Author: [Your Name]
// Date: [YYYY-MM-DD]
// Version: 0.1 (prototype)
// ============================================================

// ---- Key Parameters (change these to adapt the design) ----
// wall          = 2.0;   // mm — minimum print wall thickness
// clearance     = 0.2;   // mm — slip-fit clearance for interlocking parts
// corner_r      = 3.0;   // mm — exterior corner rounding radius

// ---- Derived Values (computed from parameters — do not edit directly) ----

// ---- Module Definitions ----

// ---- Assembly (uncomment the component to render/export) ----

Requirements for the source file:

  • All key dimensions as named variables at the top
  • At least one module per major component
  • assert() guards on critical parameters
  • Comments explaining every non-obvious design decision

2.2 — First Print and Test Log

ComponentVersionPrint dateKey measurementsPass/FailIssues found
v0.1

2.3 — Tolerance Test Results Print a tolerance test coupon for every critical interface before printing the full part. Document: nominal dimension, measured printed dimension, correction factor applied, whether the next print passed.

2.4 — Revision Log (first entries)

v0.1 → v0.2 (YYYY-MM-DD)
  - Changed wall thickness from 1.5 to 2.0 mm: v0.1 cracked during snap-fit test
  - Increased lid clearance from 0.1 to 0.25 mm: lid was too tight to open one-handed
  - Added 2 mm chamfer to all interior edges: test part showed stress fracture at sharp corners

Phase 3: Refine and Iterate (Weeks 3–5)

Goal: Make it good. Systematic improvement based on test results.

Every decision in Phase 3 must be driven by test data, not intuition. “I think it will be stronger” is not enough — print it, test it, measure it, decide.

Required Iterations

You must complete at least three complete design-print-test-revise cycles. For each cycle, document:

  1. What you changed and why (reference a specific failure mode)
  2. What you printed (component name, version, parameters used)
  3. How you tested it (specific test — not just “I tried it”)
  4. What you measured (calipers, fit test, load test)
  5. What you concluded (did the change fix the problem? Create new ones?)
  6. What you’ll change next

Phase 3 Deliverables

3.1 — Iteration Cycles (3 minimum) as described above.

3.2 — Feedback Collection Conduct a structured feedback session with your stakeholder using the Feedback Collection Template (Part 3). Document the changes you made as a result.

3.3 — Build Automation Script A script (bash or PowerShell) that builds all printable components, verifies each STL, logs results with timestamps, and archives all STLs with version tags.

#!/bin/bash
# build_all.sh — builds all project components
set -euo pipefail

VERSION="v1.0"
OUTPUT_DIR="build/$VERSION"
mkdir -p "$OUTPUT_DIR"
echo "Building $VERSION..."

components=("lid" "base" "clip" "tray")  # replace with your component names

for comp in "${components[@]}"; do
  echo "  Building: $comp"
  openscad -D "component=\"${comp}\"" -o "$OUTPUT_DIR/${comp}.stl" src/main.scad
  SIZE=$(stat -c%s "$OUTPUT_DIR/${comp}.stl")
  echo "  OK: ${comp}.stl ($SIZE bytes)"
done

echo ""
echo "All components built: $OUTPUT_DIR"

3.4 — Advanced Feature Implementation Implement at least one advanced feature from Lesson 10:

  • hull() or minkowski() for organic shaping
  • surface() for textured or embossed panels
  • children() container module
  • search() or lookup() table for material or size variants

Document which feature you chose, where it appears, and why.

3.5 — projection() Template (if applicable) If your design requires drilling or alignment of non-printed parts, produce a DXF template using projection().


Phase 4: Document and Ship (Weeks 5–6)

Goal: Make the design reproducible by someone who wasn’t there when you built it.

A design that only works because you know all the tricks isn’t finished.

Phase 4 Deliverables

4.1 — README.md

# [Project Name]

[One-sentence description]

## What You Need

### Printed Parts

- [Part name] × [qty] — [material] — [est. print time]
  - Print settings: [layer height, infill, supports?]

### Hardware

- [Item] × [qty] — [spec / source]

### Tools

- Digital calipers
- [Other tools]

## Printing Instructions

[Orientation? Supports? Infill for structural parts? Temperature?]

## Assembly Instructions

[Step-by-step numbered. Note tolerance-sensitive steps.]

## Customization

[Key parameters and what they do. How to adapt for a different use case.]

## Known Limitations

[What doesn't work perfectly. What you'd improve with more time.]

## Version History

[Summary of major revisions]

## License

[Your chosen license]

4.2 — Final Bill of Materials

PartFile / SourceMaterialPrint SettingsEst. TimeEst. Weight (g)Qty

4.3 — Final STL Files Export one STL per printable component. Name them: [project]-[component]-v[X.Y].stl

4.4 — Reflection Essay (400–600 words) Answer in essay form (not a list): What was the hardest design challenge, and how did you solve it? What would you do differently if you started over? What did you learn that surprised you? How has this project changed how you think about the physical objects you use every day?


Assessment Rubric (Option B)

Each criterion is scored 1–4.

Criterion1 — Beginning2 — Developing3 — Proficient4 — Exemplary
Parametric DesignHardcoded dimensions; no variablesSome variables; not all key dimensionsAll key dimensions parametric; named clearlyFully parametric; changing one variable produces a valid design at any scale
CSG ModelingPrimitives only; no CSGCSG used but with co-planar artifactsCSG correct; 0.001 offsets appliedNo non-manifold geometry; CSG used for all complex shapes
Tolerance & FitNo tolerance consideration; parts don’t fitTolerances guessed; some parts fitTolerances measured and calibrated; all parts fitTest coupon printed; stack-up calculated; all fits confirmed
Interlocking FeaturesNoneOne feature, poorly fitOne feature, well-designed and functionalTwo or more features; each type chosen appropriately
Build AutomationNo build scriptScript builds but no error handlingScript builds, verifies, and archivesHandles all platforms; batch variants supported
DocumentationREADME missing or minimalREADME present but incompleteREADME covers all required sectionsREADME enables a stranger to reproduce the design from scratch
IterationNo documented revisions1–2 revisions, partially documented3 revisions, fully documented with rationale4+ revisions; each driven by measured test data
Advanced FeaturesNoneOne feature presentOne feature well-integratedTwo or more; each justified in documentation
ReflectionSuperficial or missingPresent but genericGenuine reflection on specific challengesInsightful; demonstrates growth and changed thinking

Scoring: 33–36 = Distinction / 27–32 = Merit / 18–26 = Pass / Below 18 = Needs revision


Quiz — Option B: Final Project (15 questions)

  1. What is a stakeholder, and why is identifying stakeholders the first step in a design project?
  2. What is the difference between a Maker and a Design Professional, as described in this lesson?
  3. Why are open-ended interview questions preferred over yes/no questions?
  4. Write a complete User Story for this requirement: “The lid must be openable with one hand.”
  5. What are Acceptance Criteria, and how do they make a Functional Requirement testable?
  6. How does a Design Specification bridge requirements and OpenSCAD code? Give an example.
  7. True or False: Design Thinking is a linear process that ends after the first prototype.
  8. Why should you never adjust a design based on vague feedback like “it feels too tight” without first taking measurements?
  9. How can 3dm info involve a stakeholder who cannot see the 3D model visually?
  10. Your stakeholder says the holder “feels wobbly.” Describe the full engineering process from that comment to a revised design — what do you measure, what do you change, how do you verify?
  11. What is tolerance stack-up, and why does it become critical in Phase 1 rather than something to fix later?
  12. Describe the purpose of printing a tolerance test coupon before printing a full assembly.
  13. What should a revision log entry contain? Write an example entry for a wall thickness change.
  14. Your build automation script reports that one STL is 340 bytes. What does this likely indicate, and what do you do next?
  15. In your own words, explain why the Reflection Essay is a required deliverable — what is it meant to capture that a build log cannot?

Extension Problems — Option B (15)

  1. Conduct a full tolerance stack-up analysis for your assembly. Calculate worst-case misalignment across all interfaces.
  2. Design a go/no-go gauge for your most critical fit — a test part that passes only when the tolerance is correct.
  3. Write a multi-platform build script that detects the OS and uses the appropriate shell commands automatically.
  4. Implement semantic versioning in your build system: automatically increment a patch version on each successful build.
  5. Build a Git pre-commit hook that runs your build script and refuses the commit if the build fails.
  6. Create a “golden master” verification script: save the bounding box of a known-good build, then flag any future build that deviates by more than 0.1 mm.
  7. Design a three-part interlocking system where all parts can be assembled in only one correct order. Document the design intent.
  8. Write a GitHub Actions CI/CD workflow that builds all components on every push to the main branch and uploads STL artifacts.
  9. Implement lookup() tables for material-specific parameters (density, clearance, recommended wall thickness). Make switching materials a one-variable change.
  10. Produce a full DXF drilling template using projection() for any part of your design that requires holes in a non-printed substrate.
  11. Build a “measurement worksheet” that renders in OpenSCAD as a flat printed sheet listing all key dimensions — print it alongside your prototype.
  12. Conduct a formal failure mode analysis: list every way your design could fail in real use, assess probability and impact, and describe your mitigation for each.
  13. Create a parametric variant generator: a script that builds your design at 5 different scale factors and logs the bounding box and estimated weight for each.
  14. Redesign your most complex module to use children() as a container pattern, then demonstrate it with three different child geometries.
  15. Write a comprehensive retrospective document (600–1000 words) covering: what you planned vs. what you built, every significant decision point, what you would do differently, and what skills from earlier lessons proved most valuable.

Milestone Check-Ins (Option B)

WeekCheckpointWhat to Show
End of Week 1Phase 1 completeInterview notes, problem statement, measurement worksheet, FRs, design spec, sketch, BOM, risk assessment
End of Week 2First printAt least one component printed and tested; Phase 2 test log started
End of Week 3Three revisionsPhase 3 cycles 1–3 documented; feedback session complete; build script working
End of Week 4Feature completeAll components printing and fitting; advanced feature implemented
End of Week 5Documentation draftREADME draft; STL files exported; reflection drafted
End of Week 6Final submissionAll Phase 4 deliverables complete

Working Independently: Tips for Distance Learners

Work in sessions, not marathons. Two 90-minute sessions per week with clear goals produces better work than one 6-hour session. At the end of every session, write one sentence in your revision log about where you stopped and what you’ll do next.

Print early, print often. The instinct is to keep refining in CAD until the design is “perfect” before printing. Resist this. A bad print teaches you something a perfect render doesn’t. Print at 30% infill and coarse layer height for test prints — save fine settings for final parts.

Describe your problems in writing before asking for help. “My lid doesn’t close” is not a problem description. “My lid doesn’t close; the measured inner width of the base is 60.4 mm but the outer width of the lid is 60.2 mm, giving 0.2 mm per side clearance, but it still binds — I suspect the corners because the lid snaps in at a tilt” is a problem description.

Use your revision log as a thinking tool. Don’t just record what changed. Record what you expected, what happened, and what you think that means.

The design is done when it works, not when it’s perfect.


Features Checklist (both options)

Use this checklist to verify you’ve applied required curriculum concepts:

  • All key dimensions are named variables at the top of the source file
  • assert() guards protect critical parameters
  • At least two modules, each with a clear single responsibility
  • CSG operations use 0.001 mm offsets on co-planar faces
  • At least one interlocking feature (snap-fit, dovetail, thread, or friction fit)
  • Tolerance test coupon designed, printed, and measured
  • clearance constant used in at least one interface
  • Build automation script builds all components and verifies output
  • At least one advanced feature from Lesson 10
  • All STL files are manifold (no slicer warnings)
  • Stakeholder interview completed and documented
  • Functional requirements with acceptance criteria written
  • README complete (all required sections)
  • Bill of materials complete and accurate
  • At least three documented revision cycles
  • Feedback collection session completed
  • Reflection essay complete

Supplemental Resources

  • Master Rubric: Part 3 of this document / assets/3dMake_Foundation/master-rubric.md
  • Programming with OpenSCAD EPUB Textbook: assets/Programming_with_OpenSCAD.epub
  • OpenSCAD Quick Reference: https://programmingwithopenscad.github.io/quick-reference.html
  • 3DMake GitHub Repository: https://github.com/tdeck/3dmake
  • CodeSolutions Repository: https://github.com/ProgrammingWithOpenSCAD/CodeSolutions

A Final Note

Every professional product you interact with went through a version of this process. The chair you’re sitting in was measured, prototyped, printed or machined, tested, revised, and documented before it reached you. The phone in your pocket has revision histories stretching back years, with engineers who made the exact kinds of decisions you’re making now — just faster, with bigger teams, and with more sophisticated tools.

What you’re learning in this project is not just how to use OpenSCAD. You’re learning how to think through a physical design problem: how to start from a need, move through measurement and modeling, test against reality, iterate until it works, and communicate your process to others.

That thinking process transfers to any design tool, any material, and any scale. Take it seriously.

Good luck.


Part 3: Project Templates

These templates are referenced throughout Lesson 11. Complete them as part of your project documentation. They are included here so the entire lesson is self-contained — you do not need a separate file.


Template 1: Stakeholder Interview

Use this for: Phase 1 of Option B; Day 1 of Option A. Estimated duration: 45–60 minutes.


Pre-Interview Preparation

FieldYour Entry
Date
Stakeholder Name
Their Role / Relationship to Project
Interview Location
Interview Objective (what do you need to learn?)

Section 1: Context and Background (5 minutes)

  1. “Tell me about your role and how this design would fit into your life.”

    • Notes:
  2. “What problem are we trying to solve together?”

    • Notes:
  3. “Who else might be affected by this design?”

    • Notes:

Section 2: Current Situation (10 minutes)

  1. “How do you currently handle this problem — what do you do today?”

    • Notes:
  2. “What works well about what you do now?”

    • Notes:
  3. “What frustrates you most about the current situation?”

    • Notes (listen for exact words — these often become requirements):

Pain Points Summary:

  • Primary:
  • Secondary:

Section 3: Ideal Solution (15 minutes)

Use open-ended questions only. Do not suggest dimensions or shapes.

  1. “Ideally, what would a perfect solution do for you?”

    • Notes:
  2. “Walk me through how you’d use it in a typical situation.”

    • Notes:
  3. “Where would it live — what space does it need to fit into?”

    • Notes:

Constraints heard (fill in as they come up):

TypeWhat they saidDesign implication
Physical size
Weight
Temperature / environment
Durability
Budget
Timeline

Section 4: Usage Patterns (10 minutes)

  1. “How often would you use this?”

    • Daily [ ] Weekly [ ] Monthly [ ] Occasionally
    • Notes:
  2. “Who else might use it? Are there any accessibility considerations I should know about?”

    • Notes:

Section 5: Success Criteria (10 minutes)

  1. “If this design worked perfectly, how would you know? What would be different about your day?”

    • Notes:
  2. “What would make you say this design failed?”

    • Notes:

Success Criteria (draft):


Section 6: Priorities (10 minutes)

  1. “If you could only have three features, which three would matter most to you?”
    1. (Priority: /10)
    2. (Priority: /10)
    3. (Priority: /10)

Post-Interview Analysis

Key Takeaways (your summary, not a transcript):

Surprising things you didn’t expect to hear:

Open questions to follow up on:

How did this change your initial design idea?

Conducted by: ________ Date documented: ________


Template 2: Functional Requirements

Use this for: Phase 1 (Options A and B). Complete one FR block per requirement.


Project Information

FieldYour Entry
Project Name
Version
Date
Prepared By

FR1: [Name this requirement]

Priority: [ ] Critical [ ] High [ ] Medium [ ] Low

Description — what the design must do:

User Story:

“As a ______, I want to ______ so that ______.”

Acceptance Criteria (each must be independently testable):

Source (which part of the interview led to this requirement?):


FR2: [Name this requirement]

Priority: [ ] Critical [ ] High [ ] Medium [ ] Low

Description:

User Story:

“As a ______, I want to ______ so that ______.”

Acceptance Criteria:

Source:


FR3: [Name this requirement]

Priority: [ ] Critical [ ] High [ ] Medium [ ] Low

Description:

User Story:

“As a ______, I want to ______ so that ______.”

Acceptance Criteria:

Source:


Add FR4, FR5, etc. by copying the block above.


Scope

In Scope (this design will address):

  • Out of Scope (explicitly excluded):


Verification Plan

RequirementTest MethodPass ConditionStatus
FR1
FR2
FR3

Template 3: Design Specification

Use this for: Mapping FRs to OpenSCAD parameters before writing code.


Project Information

FieldYour Entry
Project
Version
Date
Designed By

Design Overview

Problem Statement (one paragraph):

Solution Approach (high-level):

Key Design Decisions:


Requirement → Parameter Mapping

For each Functional Requirement, identify the OpenSCAD variable(s) that implement it.

FROpenSCAD VariableValue / FormulaRationale
FR1
FR2
FR3

Code pattern — paste your parameter block here after writing it:

// ---- Parameters derived from requirements ----

// FR1: [Requirement name]
// [variable] = [value];  // mm — [explanation]

// FR2: [Requirement name]
// [variable] = [value];  // [explanation]

Component Breakdown

For each printed component:

Component 1: [Name]

  • Purpose:
  • Dimensions (L × W × H):
  • Material:
  • Interfaces with: (which other parts?)
  • Print orientation:
  • Supports needed: [ ] Yes [ ] No
  • Estimated print time:

Component 2: [Name] (copy block above)


Tolerance and Fit Analysis

InterfaceType of fitNominal dim.Clearance usedRationale
Part A → Part BPress / Slip / Loose

Material Selection

Primary material:

PropertyRequirementWhy this material satisfies it
Strength
Flexibility
Temperature resistance
Cost

Risk Register

RiskProbabilityImpactMitigation
H/M/LH/M/L
H/M/LH/M/L

Design Change Log

VersionDateChangeReason
0.1Initial design

Template 4: Feedback Collection

Use this for: Phase 3 — structured feedback session with your stakeholder.


Session Information

FieldYour Entry
Date
Stakeholder Name
Prototype Version
Session Duration

Section 1: First Impressions (5 minutes)

Hand the prototype to the stakeholder without explanation. Observe for 60 seconds before asking anything.

Observations (what did they do first?):

  1. “What is your first reaction to this?”

    • Response:
  2. “Is it what you expected?”

    • More than expected [ ] As expected [ ] Less than expected
    • Why:
  3. “Would you use this?”

    • Definitely [ ] Probably [ ] Maybe [ ] No
    • Why:

Section 2: Usability (15 minutes)

Ask them to demonstrate using it as they normally would. Do not explain how it works — observe.

Observations (hesitations, workarounds, confusion):

  1. “Was it easy to figure out how to use?”

    • Very easy [ ] Easy [ ] Neutral [ ] Difficult [ ] Very difficult
    • What was confusing:
  2. “Are there any parts that don’t work well together?”

    • Response:

Usability Issues Observed:

IssueSeverity (H/M/L)Stakeholder’s suggestion

Section 3: Functional Assessment (10 minutes)

Test each Functional Requirement explicitly.

RequirementResultNotes
FR1:[ ] Pass [ ] Partial [ ] Fail
FR2:[ ] Pass [ ] Partial [ ] Fail
FR3:[ ] Pass [ ] Partial [ ] Fail
  1. “What’s missing that you expected to be there?”
    • Response:

Section 4: Physical Assessment (10 minutes)

  1. Size: [ ] Too large [ ] Just right [ ] Too small

    • Notes:
  2. Weight: [ ] Too heavy [ ] Just right [ ] Too light

    • Notes:
  3. “Does the material / finish feel appropriate?”

    • Response:
  4. “Any parts that feel fragile or rough?”

    • Response:

Section 5: Overall Satisfaction (5 minutes)

CriterionScore (1–5)Comments
Overall satisfaction
Meets my needs
Design quality
Would recommend to someone else

(1 = Poor, 5 = Excellent)


Section 6: Suggestions (10 minutes)

  1. “What one change would have the biggest positive impact?”

    • Response:
  2. “What should we keep exactly as-is?”

    • Response:

Post-Session Analysis

Key Insights:

Critical Issues (block use):

Should-fix Issues (reduce satisfaction):

Design Changes Resulting from This Session:

Original designFeedback receivedChange madeRationale

Session conducted by: ________ Date: ________


Template 5: Master Project Rubric

This rubric applies to all Unit 1, 2, and 3 projects unless the project briefing specifies otherwise. Project 0 is complete/incomplete only.


Rubric Overview

Projects are scored 0–9 across three categories, 3 points each:

CategoryMax PointsWhat Is Evaluated
Problem & Solution3How well the prototype meets the identified problem or FRs
Design Quality3Complexity, originality, technical quality; evidence of iteration
Documentation3Completeness, accuracy, and thoughtfulness of all written deliverables

Category 1: Problem & Solution (0–3 points)

ScoreDescription
3Prototype clearly and effectively solves the stated problem. All FRs are met. Evidence of testing against requirements.
2Prototype mostly meets the problem. Most FRs met. Minor gaps between design and requirements.
1Prototype partially addresses the problem. Several FRs unmet or not clearly tested.
0Prototype does not address the stated problem, or no FRs were established.

Category 2: Design Quality (0–3 points)

ScoreDescription
3Design is original, well-considered, technically executed. Code is clean, uses variables and modules appropriately, and is well-commented. Print is clean. Evidence of at least one meaningful revision.
2Design is functional and shows thought. Code works but may lack structure (few comments, raw numbers). Print quality acceptable. Some iteration evident.
1Design is basic or borrowed without modification. Code has issues. Print quality has unaddressed defects.
0No meaningful original design. Print is non-functional or not completed.

Category 3: Documentation (0–3 points)

ScoreDescription
3All required sections present, complete, and specific. Reflections are thoughtful and reference specific decisions, problems, and learning. Photos included. Measurements recorded.
2Most sections present. Some sections vague or missing detail. Reflections show thought but are brief or generic.
1Documentation incomplete. Major sections missing or one-line responses. Reflections minimal.
0Documentation not submitted or essentially empty.

Score Interpretation

Total ScoreInterpretationNext Step
8–9Excellent workMove to next project
6–7Good work with room for improvementMove on; instructor may suggest revisiting one element
4–5Meets basic expectationsResubmission of specific weak areas recommended
2–3Does not meet expectationsResubmission required
0–1Missing major deliverablesMeet with instructor; create a completion plan

Resubmission Policy

Students may resubmit any project as many times as needed to improve their score. Resubmissions must include a one-paragraph explanation of what was changed and why. The resubmission score replaces the original score. -e


-e



Part IV — Final Exam

3dMake Foundation — Final Exam

Name:                                       Date:

Total Points: 100 (4 points per problem)

Instructions:

  • Answer all 25 questions
  • For code errors, identify the specific problem and explain why it’s wrong
  • For behavioral questions, show your reasoning
  • For design problems, explain your approach and why it solves the stated challenge
  • You may reference the OpenSCAD documentation and appendices
  • All work must be your own

Section 1: Error Detection & Code Analysis (Problems 1–10)

For each code block, identify any errors. If there is an error, explain what’s wrong and how to fix it. If the code is correct, state “No error” and explain what the code does.


Problem 1: Primitive Definition Error

cube([10, 10, 10], center=true);
sphere(r=5, $fn=16);
cylinder(h=20, r=8);

Is there an error in this code? If yes, identify it. If no, explain what this code renders.

Answer:


Problem 2: Transform Syntax Error

translate([5, 5, 0])
  rotate([0, 45, 0])
    cube([10, 10, 10], center=true);

Does this code have a syntax error? Explain what this code does.

Answer:


Problem 3: CSG Operation Error

cube([20, 20, 20], center=true);
difference() {
  sphere(r=12);
  cylinder(h=30, r=5, center=true);
}

What is wrong with this CSG operation? Explain the fix.

Answer:


Problem 4: Module Definition Error

module bracket(width, height, depth) {
  cube([width, height, depth], center=true);
  translate([width/2 + 2, 0, 0])
    cube([4, height, depth/2], center=true);
}
bracket(20, 15, 10);

Is there an error in this module definition or call? Why or why not?

Answer:


Problem 5: Parameter & Variable Scoping Error

wallthickness = 2;
module hollowcube(size) {
  difference() {
    cube([size, size, size], center=true);
    cube([size - wallthickness, size - wallthickness, size - wallthickness], center=true);
  }
}
hollowcube(20);

Will this code work correctly? If not, what is the problem and how would you fix it?

Answer:


Problem 6: Loop & Iteration Error

for (i = [0:5:20]) {
  translate([i, 0, 0])
    cube([4, 4, 4]);
}

Will this code produce 5 cubes? Show the positions and explain why or why not.

Answer:


Problem 7: Center Parameter Misunderstanding

cube([10, 10, 20], center=false);
sphere(r=5);

What is the relationship between these two shapes? Where would the sphere appear relative to the cube?

Answer:


Problem 8: Intersection Error

intersection() {
  cube([20, 20, 20], center=true);
  sphere(r=8, $fn=32);
}

Is there an error? What will this code render?

Answer:


Problem 9: Nested Transform Error

translate([10, 0, 0])
  rotate([0, 0, 45])
    translate([5, 0, 0])
      cube([5, 5, 5], center=true);

Are the transforms applied in the correct order? Trace the final position of the cube.

Answer:


Problem 10: Resolution Parameter Error

sphere(r=10, $fn=4);
cylinder(h=20, r=8, $fn=3);
cube([10, 10, 10]);

Identify the problem(s) with resolution in this code. What will happen when rendered?

Answer:


Section 2: Code Behavior & Theory (Problems 11–17)

For each question, show your reasoning. You may draw diagrams if helpful.


Problem 11: Vertex Coordinates

A cube is defined as cube([10, 10, 20], center=false).

a) List the XYZ coordinates of all 8 vertices.

Answer:

  • Vertex 1:
  • Vertex 2:
  • Vertex 3:
  • Vertex 4:
  • Vertex 5:
  • Vertex 6:
  • Vertex 7:
  • Vertex 8:

b) Now define the SAME cube with center=true. List the NEW coordinates of all 8 vertices.

Answer:

  • Vertex 1:
  • Vertex 2:
  • Vertex 3:
  • Vertex 4:
  • Vertex 5:
  • Vertex 6:
  • Vertex 7:
  • Vertex 8:

Problem 12: Sphere Geometry

Explain the difference between sphere(r=10, $fn=8) and sphere(r=10, $fn=128).

Which would you use for a prototype and which for final printing? Why?

Answer:


Problem 13: Transform Order

Given this code:

translate([10, 0, 0])
  rotate([0, 0, 45])
    cube([5, 5, 5], center=true);

Does the order matter? What if you swap translate and rotate? Show both final positions.

Answer:


Problem 14: Boolean Operation Behavior

You have a solid cube and you want to create a hole through it. Which CSG operation would you use: union(), difference(), or intersection()?

Explain your choice and write pseudocode showing how you’d accomplish this.

Answer:


Problem 15: Parametric Design Advantage

Compare these two approaches:

Approach A: Hard-coded cube with fixed dimensions

cube([10, 10, 20]);

Approach B: Parametric cube

module parametricbox(width, height, depth) {
  cube([width, height, depth], center=true);
}
parametricbox(10, 10, 20);

Why is Approach B better for design iteration? Give an example of how you’d use it.

Answer:


Problem 16: Scale Transform Behavior

If you apply scale([2, 1, 0.5]) to a cube([10, 10, 10], center=true), what are the NEW dimensions of the cube?

Answer — New dimensions:

Show your calculation:


Problem 17: Library Organization

You’ve created three useful modules:

  • bracket(width, height, depth)
  • hollowcube(size, wallthickness)
  • connectorpin(diameter, height)

How would you organize these into a reusable library? What file structure would you create and why?

Answer:


Section 3: Design & Problem-Solving (Problems 18–25)

These problems test your ability to design solutions, debug real-world issues, and think creatively.


Problem 18: Tolerance Design Challenge

You’re designing a snap-fit connector. The male part has a thickness of 2mm. The female slot needs to accommodate this part with enough flexibility to snap but not fall out.

Should the slot be:

  • a) Exactly 2mm wide
  • b) 2.1mm wide
  • c) 1.9mm wide
  • d) 2.5mm wide

Explain your choice and the design thinking behind it.

Answer:


Problem 19: Design Iteration Problem

You print a keycap with keysize=12 and the text embossing is too shallow to feel. Your code uses:

linear_extrude(height=1)
  text("A", size=8);

What parameter(s) would you adjust to make the embossing deeper? Show your new code.

Answer:


Problem 20: Error Diagnosis

Your 3dMake build fails with this error: “Geometry is non-manifold.” You have this code:

difference() {
  cube([20, 20, 20], center=true);
  cylinder(h=30, r=4, center=true);
}

Why might this fail? What’s the common fix for non-manifold geometry?

Answer:


Problem 21: Multi-Part Assembly

You’re designing a two-part box (lid + base). The base has dimensions [50, 30, 20]. The lid should sit on top of the base.

Write parametric modules for both parts and show how you’d position them together. Include appropriate positioning logic.

Answer:

module base(length, width, height) {
  // Your code here
}

module lid(length, width, height) {
  // Your code here
}

// Positioning code here:

Problem 22: Optimization Challenge

You have a design that takes 5 minutes to render. You notice you have:

sphere(r=10, $fn=256);
cylinder(h=20, r=8, $fn=256);
cube([20, 20, 20]);

Which parameter(s) would you reduce to speed up rendering while maintaining acceptable quality for a prototype? Explain your choices.

Answer:


Problem 23: Real-World Constraint Problem

A stakeholder requests a custom handle for a tool. They specify:

  • Must fit a hand (approximately 80mm long)
  • Must accommodate fingers 60mm long inside
  • Wall thickness must be at least 3mm for durability
  • Should be ergonomic (slightly curved)

Sketch or describe a parametric design for this handle. What parameters would you expose to allow customization?

Answer:


Problem 24: Code Reusability Challenge

You’ve created a single keycap module. Now you need to create a keyboard with 5 keys arranged in a row, spaced 15mm apart.

Write code using a loop that creates 5 keycaps with letters A–E, properly spaced.

Hint: In OpenSCAD, strings are indexed like lists. "ABCDE"[0] returns "A", "ABCDE"[1] returns "B", and so on. The len() function returns the number of characters in a string.

Answer:

module keycap(letter, keysize=10) {
  // Keycap code here (you can assume this exists)
}

// Your loop code here:

Problem 25: Design Thinking & Iteration

You’ve printed Iteration 1 of a product and measured the results. The wall thickness is 3mm but feels too fragile. In Iteration 2, you increased it to 5mm, and now it feels too rigid and won’t flex as intended.

For Iteration 3, what thickness would you try and why? How would you make this decision more scientific/data-driven?

Answer:


Bonus Challenge (Optional, +5 points)

Design a parametric model for a custom assistive technology device (e.g., a tactile measuring tool, a custom gripper, an adapted eating utensil, etc.).

  • Identify the user’s specific need
  • Specify the key dimensions and parameters
  • Write at least one module with realistic dimensions
  • Explain how the design would be tested and iterated

Answer:

// Your design here:

User Need:

Parameters:

Testing Plan:


Scoring Rubric

PointsCriteria
4Correct answer with clear, complete explanation; demonstrates deep understanding
3Mostly correct answer; minor gaps in explanation or reasoning
2Partially correct; shows some understanding but has significant gaps
1Minimal effort; shows limited understanding
0No answer or completely incorrect

Total Possible: 100 + 5 bonus = 105 points


References You May Use


End of Final Exam

Submission Instructions:

  1. Answer all 25 questions completely
  2. Show your work for calculations and reasoning
  3. Include code samples where requested
  4. Submit as a PDF with your name and date
  5. Scoring will be based on correctness, clarity, and depth of understanding

Good luck!




INSTRUCTOR APPENDIX

Not for student distribution


Exam Administration Notes

Sequencing — Problem 20

Problem 20 tests non-manifold geometry diagnosis, which is formally introduced in Lesson 10.

  • If administered before Lesson 10 is complete: Problem 20 is not counted in the passing threshold for Lessons 1–9. Consider adding a notice directing students to skip and return to it after Lesson 10.
  • If administered after all 10 lessons: No changes needed — the problem is fair game.

Answer Keys & Rubrics

Problem 20 — Non-Manifold Geometry (Extended Model Answer)

The exam version tests the core concept with a simple case. The extended variant below can be used as an enrichment rubric or for a more advanced cohort. It contains three non-manifold issues:

// PROBLEM CODE — find and fix all issues
difference() {
  cube([40, 40, 25]);
  translate([10, 10, 0])        // NON-MANIFOLD: co-planar bottom face
    cylinder(r=8, h=25, $fn=24);
  translate([20, 20, 25])       // NON-MANIFOLD: co-planar top face
    cylinder(r=5, h=10, $fn=24);
}

// NON-MANIFOLD: these two cubes share a face (just touching, not overlapping)
translate([40, 0, 0])  cube([15, 40, 25]);
translate([55, 0, 0])  cube([15, 40, 25]);
  1. Co-planar bottom face — the first cylinder’s base is flush with the cube’s base (z=0).
  2. Co-planar top face — the second cylinder starts exactly at the cube’s top (z=25).
  3. Touching faces — the two side cubes share an exact face (just touching, not overlapping).

Corrected version:

difference() {
  cube([40, 40, 25]);

  // FIX 1: extend cylinder 0.001 below base AND above top
  translate([10, 10, -0.001])
    cylinder(r=8, h=25.002, $fn=24);

  // FIX 2: extend the top-entry cylinder 0.001 into the solid
  translate([20, 20, 25 - 9.999])
    cylinder(r=5, h=10.001, $fn=24);
}

// FIX 3: overlap the two touching cubes by 0.001 and use explicit union()
union() {
  translate([40, 0, 0])  cube([15.001, 40, 25]);
  translate([55, 0, 0])  cube([15, 40, 25]);
}

Extended rubric (10 points):

  • Identifies all 3 issues: 3 pts
  • Fixes issue 1 (co-planar bottom) correctly: 2 pts
  • Fixes issue 2 (co-planar top) correctly: 2 pts
  • Fixes issue 3 (touching faces) correctly: 2 pts
  • Model builds cleanly with no CGAL warnings: 1 pt

Problem 24 — Keycap Loop (Model Answer)

letters  = "ABCDE";
keysize  = 10;
key_gap  = 15;

for (i = [0 : len(letters) - 1]) {
  translate([i * (keysize + key_gap), 0, 0])
    keycap(letters[i], keysize);
}

Expected output: 5 keycaps labeled A, B, C, D, E, evenly spaced in a row.

Rubric (4 points):

  • Correct for with range syntax: 1 pt
  • Correct string indexing letters[i]: 1 pt
  • Correct translate() to space keys apart: 1 pt
  • All 5 keycaps render without errors: 1 pt

Extension Projects (Optional / Post-Exam)

These projects are not part of the graded exam. Assign as enrichment after students complete all 10 lessons.


Extension A — Recursive Fractal Geometry

Recommended after Lesson 3. Demonstrates recursive OpenSCAD for visual and mathematical interest.

Warning: Level 4+ will take minutes to render — stay at Level ≤ 3.

module menger(size=27, level=2) {
  if (level == 0) {
    cube(size, center=true);
  } else {
    s3 = size / 3;
    difference() {
      cube(size, center=true);
      for (x=[-1,0,1]) for (y=[-1,0,1]) for (z=[-1,0,1]) {
        if ((x==0 ? 1 : 0) + (y==0 ? 1 : 0) + (z==0 ? 1 : 0) >= 2) {
          translate([x*s3, y*s3, z*s3])
            cube(s3 + 0.002, center=true);
        }
      }
    }
    for (x=[-1,0,1]) for (y=[-1,0,1]) for (z=[-1,0,1]) {
      if (!((x==0?1:0)+(y==0?1:0)+(z==0?1:0) >= 2)) {
        translate([x*s3, y*s3, z*s3])
          menger(s3, level-1);
      }
    }
  }
}

menger(size=27, level=2);  // change level to 0, 1, or 2

Extension B — Generative Pattern Arrays

Demonstrates list comprehensions and math functions for artistic/functional array generation.

plate_w = 120;
plate_d = 80;
plate_h = 3;

hole_d    = 4;
grid_s    = 8;
wave_amp  = 3;
wave_freq = 0.1;

module perforated_panel() {
  difference() {
    cube([plate_w, plate_d, plate_h]);
    cols = floor(plate_w / grid_s);
    rows = floor(plate_d / grid_s);
    for (cx = [1 : cols - 1]) {
      for (ry = [1 : rows - 1]) {
        x = cx * grid_s;
        y = ry * grid_s;
        wave_val = sin(x * wave_freq * 360) * sin(y * wave_freq * 360);
        d = hole_d + wave_amp * wave_val;
        if (d > 0.5) {
          translate([x, y, -0.001])
            cylinder(d=d, h=plate_h + 0.002, $fn=16);
        }
      }
    }
  }
}

perforated_panel();

Extension C — Multi-Platform Build Pipeline

Full build pipeline scripts for all three shell environments.

Makefile (Linux/macOS)

.PHONY: all build clean variants archive test

SRC     := src/main.scad
OUTPUT  := build/main.stl
WIDTHS  := 20 30 40 50 80

all: build test archive

build: $(OUTPUT)

$(OUTPUT): $(SRC) | build/
  openscad -o $@ $<
  3dm info

build/:
  mkdir -p build build/variants build/logs

clean:
  rm -rf build/

variants: build/
  @for w in $(WIDTHS); do \
    echo "Building width=$$w..."; \
    openscad -D "width=$$w" -o "build/variants/main_w$$w.stl" $(SRC); \
  done

archive: build/
  $(eval TS := $(shell date +%Y%m%d_%H%M%S))
  mkdir -p "archives/$(TS)"
  cp $(OUTPUT) "archives/$(TS)/"
  cp $(SRC)    "archives/$(TS)/"
  3dm info > "archives/$(TS)/BUILD_INFO.txt"

test: build/
  @for w in 10 30 80; do \
    openscad -D "width=$$w" -o "/tmp/test_w$$w.stl" $(SRC) && \
    echo "  width=$$w: OK" || echo "  width=$$w: FAILED"; \
  done

PowerShell (Windows)

param($Width = 30)

$src    = "src\main.scad"
$output = "build\main.stl"
$widths = @(20, 30, 40, 50, 80)

task init {
    New-Item -Force -ItemType Directory -Path "build","build\variants","build\logs" | Out-Null
}

task build init, {
    exec { openscad -D "width=$Width" -o $output $src }
    exec { 3dm info }
}

task clean {
    Remove-Item -Recurse -Force "build" -ErrorAction SilentlyContinue
}

task variants init, {
    foreach ($w in $widths) {
        exec { openscad -D "width=$w" -o "build\variants\main_w$w.stl" $src }
    }
}

task archive build, {
    $ts  = Get-Date -Format "yyyyMMdd_HHmmss"
    $dir = "archives\$ts"
    New-Item -Force -ItemType Directory -Path $dir | Out-Null
    Copy-Item $output $dir
    Copy-Item $src    $dir
    & 3dm info | Out-File "$dir\BUILD_INFO.txt" -Encoding UTF8
}

task test init, {
    foreach ($w in @(10, 30, 80)) {
        try {
            exec { openscad -D "width=$w" -o "build\test_w$w.stl" $src }
            Write-Host "  width=$w: OK"
        } catch { Write-Warning "  width=$w: FAILED" }
    }
}

task all build, test, archive

CMD Batch (Windows Legacy)

@echo off
SET ACTION=%1
IF "%ACTION%"=="" SET ACTION=all

IF "%ACTION%"=="build"    GOTO :BUILD
IF "%ACTION%"=="clean"    GOTO :CLEAN
IF "%ACTION%"=="variants" GOTO :VARIANTS
IF "%ACTION%"=="archive"  GOTO :ARCHIVE
IF "%ACTION%"=="all"      GOTO :ALL

:ALL
CALL :BUILD_STEP
IF %ERRORLEVEL% NEQ 0 EXIT /b 1
CALL :VARIANTS_STEP
CALL :ARCHIVE_STEP
GOTO :EOF

:BUILD_STEP
mkdir build 2>nul
openscad -o build\main.stl src\main.scad
IF %ERRORLEVEL% NEQ 0 (echo [BUILD] FAILED & EXIT /b 1)
3dm info
EXIT /b 0

:CLEAN
rmdir /s /q build 2>nul
GOTO :EOF

:VARIANTS_STEP
mkdir build\variants 2>nul
FOR %%W IN (20 30 40 50 80) DO (
    openscad -D "width=%%W" -o "build\variants\main_w%%W.stl" src\main.scad
)
EXIT /b 0

:ARCHIVE_STEP
FOR /f "tokens=2 delims==" %%D IN ('wmic os get localdatetime /value') DO SET DT=%%D
SET TS=%DT:~0,8%_%DT:~8,6%
mkdir "archives\%TS%" 2>nul
copy build\main.stl "archives\%TS%\" >nul
copy src\main.scad  "archives\%TS%\" >nul
3dm info >> "archives\%TS%\BUILD_INFO.txt" 2>&1
EXIT /b 0

Quick Reference — Shell Equivalents

Taskbash (Linux/macOS)PowerShell (Windows)CMD (Windows)
Build3dm build3dm build3dm build
Info3dm info3dm info3dm info
Parameter (number)-D "width=50"-D "width=50"-D "width=50"
Parameter (string)-D 'label="A"'-D 'label="A"'-D "label=""A"""
Loop over listfor x in a b c; do ... doneforeach ($x in @(...)) {...}FOR %%X IN (a b c) DO ...
Make directorymkdir -p dirNew-Item -Force -ItemType Directory dirmkdir dir 2>nul
Copy filecp src dstCopy-Item src dstcopy src dst
Check exit codeif [ $? -ne 0 ]if ($LASTEXITCODE -ne 0)IF %ERRORLEVEL% NEQ 0
Write to fileecho text > file"text" | Out-File fileecho text > file
Append to fileecho text >> file"text" | Add-Content fileecho text >> file
Date/timedate +%Y%m%d_%H%M%SGet-Date -Format "yyyyMMdd_HHmmss"wmic os get localdatetime
File size (bytes)stat -c%s file(Get-Item file).LengthFOR /F "tokens=4" %%S IN ('dir file')
Watch for changesls src/*.scad | entr 3dm build(see Lesson 9 watcher)(use PowerShell)
-e


Part V — Quick Reference Guide

3dMake Foundation Quick Reference Guide

Fast lookup for lessons, projects, resources, and common tasks

Lesson Quick Reference

All 11 Lessons at a Glance

#TitleDurationLevelMain TopicsKey Project
1Environmental Configuration60-90mBeginnerSetup, project structure, 3dm buildNone
2Geometric Primitives & CSG60mBeginnerPrimitives, CSG operations, debuggingNone
3Parametric Architecture60mBeginner+Modules, libraries, parametersNone
4AI Verification45-60mIntermediate3dm info, validation, design documentationNone
5Safety & Physical Interface60-90mIntermediateSafety protocols, materials, pre-print checksNone
63dm Commands & Text60-90mIntermediate3dm info/preview/orient/slice, embossingKeycap
7Parametric Transforms75-90mIntermediate+Transforms, multi-part design, assemblyPhone Stand
8Advanced Parametric Design90-120mAdvancedTolerance, interlocking features, snap-fitsStackable Bins
9Automation & Workflows60-90mAdvancedPowerShell scripting, batch processing, CI/CD[key] Batch Automation
10Troubleshooting & Mastery120-150mAdvancedMeasurement, QA testing, diagnostics[dice] QA + Audit
11Stakeholder-Centric Design90-120mAdvanced+Design thinking, user research, iteration[beads] Jewelry Holder

4 Reference Appendices

Quick links to comprehensive reference materials:

AppendixFocusSizeUse When
A: Comprehensive Slicing GuidePrusaSlicer, Bambu Studio, Cura, OrcaSlicer configuration1,500+ linesSlicing questions, slicer reference
B: Material Properties & Selection GuideShrinkage data, print settings, material properties1,200+ linesChoosing material, troubleshooting prints
C: Tolerance Testing & Quality Assurance MatrixQA procedures, tolerance validation methods1,200+ linesQuality verification, measurement techniques
D: PowerShell Integration for SCAD WorkflowsBatch processing, automation scripts, workflow integration1,100+ linesBuilding automation, batch processing

Learning Paths

Path 1: Complete Mastery (18-22 hours)

-> Lessons 1-11 + All Appendices

Best for: Complete skill development, comprehensive understanding

Path 2: Design Focus (12-15 hours)

-> Lessons 1-3, 6-8, 11 + Appendices A, B, C

Best for: Experienced makers new to programmatic CAD

Path 3: Project-Based (14-18 hours)

-> Lessons 1-5 (Foundations) -> 6 (Keycap) -> 7 (Stand) -> 8 (Bins) -> 9 (Automation) -> 10 (Troubleshooting) -> 11 (Leadership)

Best for: Learning through building

Path 4: Safety & Printing (10-12 hours)

-> Lessons 1, 2, 5, 6, 10 + Appendices A, B, C

Best for: Focus on practical printing and quality

3dm Command Reference

Essential Commands

# Setup
./3dm setup                 # Initial configuration

# Development
3dm edit-model file.scad    # Open in editor
3dm build src/main.scad     # Generate STL from SCAD

# Inspection
3dm info file.scad      # Text analysis (AI if configured)
3dm preview file.scad       # Generate 2D tactile preview

# Optimization
3dm orient file.scad        # Suggest print orientation

# Production
3dm slice file.scad         # Generate G-code
3dm send build/main.gcode   # Send to printer

# Libraries
3dm lib list                # Show available libraries
3dm lib install BOSL2       # Install a library

Command Chaining

# Sequential with error handling
3dm build src/main.scad && 3dm slice src/main.scad && echo "Ready to print"

# Loop through files
for f in src/*.scad; do 3dm build "$f" && 3dm slice "$f"; done

OpenSCAD Quick Reference

Primitives

cube([width, height, depth], center=false);
sphere(r=radius, $fn=32);
cylinder(r=radius, h=height, $fn=32);

Transforms

translate([x, y, z]) { ... }
rotate([x_deg, y_deg, z_deg]) { ... }
scale([x, y, z]) { ... }

Boolean Operations

union() { shape1; shape2; }         // Combine
difference() { shape1; shape2; }    // Subtract
intersection() { shape1; shape2; }  // Keep overlap

Modules

module my_shape(size) {
  cube([size, size, size]);
}
my_shape(20);   // Call module

Parameters

width = 50;     // mm
height = 30;    // mm
inner = width - 2*wall;

Projects Reference

Project 1: Parametric Keycap (Lesson 6)

Key Parameters:

key_size = 18;      // mm
key_height = 12;    // mm
wall = 1.2;         // mm
letter = "A";       // Character

Variants to Try:

  • Small: 12mm, 10mm height
  • Medium: 18mm, 12mm height
  • Large: 24mm, 14mm height

Files:

  • Code: Lesson 6 (Keycap section)
  • Output: keycap_X.scad, keycap_X.stl

Project 2: Phone Stand (Lesson 7)

Key Parameters:

phone_width = 75;   // mm
base_width = 85;    // mm
angle = 60;         // degrees
lip_height = 15;    // mm

Configurations:

PhoneWidthAngleResult
iPhone60mm60Portrait viewing
iPad100mm40Landscape viewing
Tablet150mm35Document viewing

Files:

  • Code: Lesson 7 (Phone Stand section)
  • Output: stand_X.stl, stand_X.gcode

Project 3: Stackable Bins (Lesson 8)

Key Parameters:

bin_w = 80;         // width (mm)
bin_d = 120;        // depth (mm)
bin_h = 60;         // height (mm)
wall = 2;           // thickness (mm)
stack_clear = 0.6;  // tolerance (mm) - CRITICAL

Tolerance Testing:

stack_clear = 0.4mm  -> Too tight (hard to stack)
stack_clear = 0.6mm  -> Ideal (smooth fit)
stack_clear = 0.8mm  -> Too loose (unstable)

Files:

  • Code: Lesson 8 (Bins section)
  • Output: bin_*.stl, tolerance_matrix.md

Code Template Library

Generic Parametric Part Template

// ====== PARAMETERS (customize here) ======
param1 = 50;        // mm
param2 = 30;        // mm
param3 = 5;         // mm
$fn = 32;           // Resolution (lower = faster)
// ====== CALCULATED PARAMETERS ======
derived_param = param1 - 2*param3;
// ====== MODULES ======
module my_part() {
  cube([param1, param2, param3]);
}
// ====== MAIN ======
my_part();

Hollow Box Template

outer_size = 50;
inner_size = 40;
wall = 5;
difference() {
  cube([outer_size, outer_size, outer_size]);
  translate([wall, wall, wall])
    cube([inner_size, inner_size, inner_size]);
}

Batch Build Script Template

#!/bin/bash
# batch_build.sh

for scad in src/*.scad; do
  name=$(basename "$scad" .scad)
  echo "Building: $name"
  3dm build "$scad" || continue
  cp "build/main.stl" "build/${name}.stl"
done

Troubleshooting Quick Fixes

Problem: Model won’t build

Diagnosis:

3dm info file.scad
# Look for error messages

Common Fixes:

  • Check syntax (missing semicolons, parentheses)
  • Look for non-manifold geometry
  • Use $fn=12 for faster test renders

Problem: Parts don’t fit together

Diagnosis:

  • Print and test fit
  • Measure with calipers

Solution:

  • Adjust stack_clear (smaller = tighter)
  • Increase wall thickness
  • Test with tolerance matrix

Problem: Embossed text looks bad

Diagnosis:

  • Check preview in slicer
  • Use 3dm preview for tactile version

Solution:

  • Increase letter_raise (deeper emboss)
  • Use larger $fn in text()
  • Simplify character or use different size

Problem: Print fails

Diagnosis:

  • Check slicer layer preview
  • Verify bed adhesion and temperature

Solution:

  • Check pre-print checklist (Lesson 5)
  • Adjust print temperature
  • Verify bed is level and clean

Assessment Checklist

Lesson Completion Criteria

  • Watched/read entire lesson
  • Completed all step-by-step tasks
  • Reached all checkpoints
  • Answered all quiz questions (self-assessed)
  • Attempted at least 3 extension problems
  • Documented findings

Project Completion Criteria

  • Code builds without errors
  • All parameters functional
  • STL generated and inspected
  • Measurements documented
  • Assembly tested (if multi-part)
  • README or documentation included

Quality Standards

  • Code is well-commented
  • Parameters have clear names and units
  • Modules are reusable
  • Design follows DRY principle
  • Documentation is complete

Official Docs

Tutorials

Community

Tips & Tricks

Debugging

Tip

Lower $fn to 8–12 during development for fast renders, then raise it to 32–64 for final export. High $fn values (especially with Minkowski) can make renders take minutes.

  • Lower $fn to 8-12 for faster renders during development
  • Use 3dm info frequently to catch issues early
  • Test components individually before assembling
  • Generate 3dm preview for 2D tactile verification

Design

  • Keep parameters at the top of file for easy modification
  • Use descriptive names (not w, use width)
  • Include units in comments
  • Document parameter ranges (e.g., // 0-100 mm)

Organization

  • Use src/ for SCAD files, lib/ for modules, build/ for outputs
  • Create variants by copying files and renaming
  • Use bash scripts for batch operations
  • Archive successful builds with timestamps

Accessibility

Important

For accessible design, always use 3dm info to verify non-visual usability and 3dm preview to generate a tactile inspection image. Document all measurements clearly and test assembly without visual guidance.

  • Always use 3dm info to verify non-visual usability
  • Generate 3dm preview for tactile inspection
  • Document measurements clearly
  • Test assembly without visual guidance

Glossary

TermDefinition
CSGConstructive Solid Geometry - combining shapes using union/difference
ManifoldWater-tight geometry with clear inside/outside
ParametricDriven by variables; changing parameters updates design
ToleranceAcceptable variation in dimensions
Stack-upCumulative error from multiple tolerances
ModuleReusable code block in OpenSCAD
$fnResolution parameter (higher = more detail but slower)
G-codeMachine instructions for 3D printer
STL3D model file format for printing

Quick Answers

Q: Where do I put my SCAD files?
A: In the src/ folder of your 3dMake project

Q: How do I test if my design will fit?
A: Use the tolerance testing matrix; print variants with different parameters

Q: What should I measure after printing?
A: Critical dimensions and compare to design specifications

Tip

Non-manifold fix: Use the 0.001 offset rule — translate([0, 0, -0.001]) before subtracting and add 0.002 to the cutting shape’s height.

Q: How do I fix non-manifold geometry?
A: Use the 0.001 offset rule: translate([0, 0, 0.001]) before subtracting

Q: Can I combine multiple SCAD files?
A: Yes, use include <path/to/file.scad> or use <path/to/file.scad>

Q: How do I make designs accessible?
A: Use 3dm info and 3dm preview and include written measurements/descriptions


  1. Programming with OpenSCAD. https://programmingwithopenscad.github.io/

  2. CadHub. OpenSCAD Review. https://learn.cadhub.xyz/blog/openscad-review/ ↩2

  3. Deck, T. (2025). 3DMake. GitHub. https://github.com/tdeck/3dmake ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9

  4. Class Central. OpenSCAD Courses. https://www.classcentral.com/subject/openscad

  5. ZenML. LLM-Powered 3D Model Generation. https://www.zenml.io/llmops-database/llm-powered-3d-model-generation-for-3d-printing ↩2 ↩3

  6. Ohio State University EHS. https://ehs.osu.edu/kb/3d-printer-safety ↩2 ↩3 ↩4 ↩5

  7. CDC/NIOSH. https://www.cdc.gov/niosh/blogs/2024/safe-3d-printing.html

  8. Washington State DoH. https://doh.wa.gov/community-and-environment/schools/3d-printers ↩2 ↩3

  9. RIT EHS. https://www.rit.edu/ehs/3-d-printer-safety ↩2

  10. UTK EHS. https://ehs.utk.edu/index.php/table-of-policies-plans-procedures-guides/3d-printer-safety/

  11. Gonzalez Avila et al. https://thomaspietrzak.com/bibliography/gonzalez24.pdf

  12. Reddit. https://www.reddit.com/r/openscad/comments/1fxj8xv/

  13. OpenSCAD Issue #6297. https://github.com/openscad/openscad/issues/6297

  14. Hacker News. https://news.ycombinator.com/item?id=46338565 ↩2

  15. OpenSCAD Issue #6114. https://github.com/openscad/openscad/issues/6114

  16. Tom’s Hardware. https://www.tomshardware.com/3d-printing/how-to-repair-stl-files-in-meshlab

  17. https://services.slcpl.org/creativelab

  18. https://www.slcolibrary.org/what-we-have/create

  19. https://www.weberpl.lib.ut.us/use-your-library/makerspaces

  20. https://library.washco.utah.gov/st-george/makerspace/

  21. https://library.loganutah.org/about_us/services/makerspace.php

  22. https://www.lib.utah.edu/services/3d-printing.php

  23. https://stem.utah.gov/innovationhubnetwork/ ↩2 ↩3

  24. 3DMake GitHub Repository — Command reference including 3dm info. https://github.com/tdeck/3dmake

  25. Digital Calipers Measurement Technique — see Appendix B of this document.

BackMatter

This BackMatter section collects supplementary materials, appendices, and reference content for the book.

Advanced Study Guide

CLI Foundations & 3dMake Certification

Format: Each lesson contains 10 questions.

  • Questions 1–5 (Fix the Code): Each block contains one or more deliberate errors. Identify every error and write a corrected version.
  • Questions 6–10 (Comment the Code): Each block is correct but uncommented. Add a meaningful inline or block comment to every significant line or section.

PART 1 — PowerShell


PowerShell — Lesson Pre: Your First Terminal

Fix the Code (Questions 1–5)

Q1. This script is supposed to show the current directory and list files, but it uses the wrong commands.

location
list -names

Q2. The user wants to create a file with content, then read it back. Two commands are wrong.

print "Hello PowerShell" > notes.txt
read notes.txt

Q3. The user wants to open a file in Notepad. The path separator and command name are wrong.

notepad notes/txt

Q4. This snippet is supposed to stop a running command, clear the screen, and go home. One keyboard shortcut description is wrong, and one command is wrong.

# Press Ctrl+X to stop a running command
# Press Ctrl+L to clear the screen
# Type the following and press Enter to go home:
home

Q5. This script should save the file listing to a file, then open it. The redirection operator and the open command are both wrong.

ls -n >> directory_list.txt
open directory_list.txt

Comment the Code (Questions 6–10)

Q6. Add a comment to every line explaining what it does.

pwd
ls -n
cd Documents
pwd
ls -n

Q7. Add comments explaining what each part of this file-creation workflow does.

echo "Test content" > test.txt
cat test.txt
echo "Line 2" >> test.txt
cat test.txt

Q8. Add comments explaining each step of this tab-completion demonstration script.

cd ~
ls -n
cd Doc

(Note: the third line is intentionally incomplete — the user would press Tab here.)

Q9. Add comments to this output-redirection workflow explaining why each step is needed.

ls -n > big_list.txt
notepad.exe big_list.txt
ls -n | findstr "scad"

Q10. Add comments explaining each keyboard shortcut and what it accomplishes for screen reader users.

# Up Arrow
# Down Arrow
# Tab
# Ctrl+C
# Ctrl+L

PowerShell — Lesson 0: Getting Started — Paths and the Shell

Fix the Code (Questions 1–5)

Q1. This script navigates to a nested folder but uses wrong path notation for Windows PowerShell.

cd ~/Documents/Projects
cd ../
pwd

(Hint: the second line uses a Linux-style relative path — valid, but the first line also has an issue on some systems. Focus on the separator convention and the go-home shortcut used.)

Q2. The user wants to navigate to a folder whose name contains a space. The command is missing required syntax.

cd My Projects

Q3. This script checks the current path, then navigates using an absolute path that is wrongly constructed.

pwd
cd C:/Users/Student/Documents

Q4. The script is supposed to list only file names (not full details). The flag is wrong.

ls -l

Q5. The 3DMake project setup sequence has a command error — the wrong operator is used to initialize the project.

mkdir ~/Documents/3d_projects/my_cube
cd ~/Documents/3d_projects/my_cube
3dm create

Comment the Code (Questions 6–10)

Q6. Add comments explaining what each path shortcut means and when you would use it.

cd ~
cd ./subfolder
cd ../
cd $HOME

Q7. Add comments explaining the purpose of each line in this path-oriented script.

pwd
ls -n
cd Documents
pwd
cd ~
pwd

Q8. Add comments explaining what tab completion is doing at each step.

cd ~/D
cd ~/Documents/3d_p
ls -n

(Note: first two lines show partial paths where Tab would be pressed.)

Q9. Add comments to this 3DMake quick-start sequence explaining each command’s role.

cd ~/Downloads/3dmake
./3dm setup
mkdir ~/Documents/3d_projects
mkdir ~/Documents/3d_projects/my_cube
cd ~/Documents/3d_projects/my_cube
3dm new
ls -n

Q10. Add comments explaining each line of this prompt-anatomy reference.

# PS C:\Users\Student\Documents>
pwd
ls -n
cd ..
pwd

PowerShell — Lesson 1: Navigation

Fix the Code (Questions 1–5)

Q1. This script tries to list only .scad files but uses the wrong filter syntax for PowerShell.

ls -n *.scad
ls -n | findstr scad

(The first line is correct — identify the error in the second line.)

Q2. The script should navigate deep into a project structure and then return home in one command. The return command is wrong.

cd ~/Documents/3d_projects/my_cube/src
cd /home

Q3. This loop is supposed to list all files but it uses a nonexistent PowerShell command.

foreach ($f in ls -n *.txt) {
    print $f
}

Q4. The user wants to find all .stl files and save the results. The wildcard and redirection are both wrong.

ls -n build/%.stl > results.txt

Q5. This script navigates to a project and verifies the build output, but the path separator and verify command are wrong.

cd ~/Documents\3d_projects\my_cube
ls -n build/
Test-Exist build/main.stl

Comment the Code (Questions 6–10)

Q6. Add comments explaining each ls flag and what it produces.

ls -n
ls -n *.scad
ls -n | findstr ".stl"
ls -n -af

Q7. Add comments to this multi-level navigation script.

cd ~/Documents/3d_projects
pwd
cd my_cube
pwd
cd src
pwd
cd ../../..
pwd

Q8. Add comments explaining why each command exists in this verification workflow.

cd ~/Documents/3d_projects/my_cube
pwd
ls -n
ls -n src/
ls -n build/

Q9. Add comments explaining the wildcard patterns used in each line.

ls -n *.scad
ls -n part?.stl
ls -n *_final*
ls -n project_[1-3].scad

Q10. Add comments to this screen-reader-friendly output-saving workflow.

ls -n > file_list.txt
notepad.exe file_list.txt
ls -n | findstr "scad"
ls -n | findstr "scad" > scad_list.txt
notepad.exe scad_list.txt

PowerShell — Lesson 2: File and Folder Manipulation

Fix the Code (Questions 1–5)

Q1. This script tries to copy a file but uses the wrong PowerShell cmdlet name.

cp source.txt destination.txt

Q2. The user wants to delete a file but mistakenly uses the Linux command.

rm old_draft.scad

Q3. This script creates a backup of an entire project folder, but the flag for recursive copy is missing.

Copy-Item my_cube backup_cube

Q4. The folder-creation command is right but the subsequent verification uses the wrong flag for listing directories only.

mkdir Models
mkdir Prints
mkdir Docs
ls -n -files

Q5. This safe-deletion sequence is out of order — verification happens after deletion instead of before.

Remove-Item old_test.scad
ls -n *.scad

Comment the Code (Questions 6–10)

Q6. Add comments explaining what each file operation does and what to verify afterwards.

New-Item -ItemType File -Name "design.scad"
Copy-Item design.scad design_backup.scad
Move-Item design.scad archive/design_v1.scad
ls -n

Q7. Add comments to this folder-structure creation script.

mkdir 3DProjects
cd 3DProjects
mkdir Models
mkdir Prints
mkdir Docs
mkdir Backups
ls -n

Q8. Add comments explaining the safe backup-before-edit pattern.

Copy-Item project.scad project_backup.scad
ls -n *.scad
notepad.exe project.scad
Copy-Item project.scad project_v2.scad

Q9. Add comments to this wildcard file-management sequence.

ls -n *.tmp
Remove-Item *.tmp
ls -n *.scad
Copy-Item *.scad backup/
ls -n backup/

Q10. Add comments explaining what each step of this project-archiving script does.

$date = Get-Date -Format "yyyyMMdd"
$archiveName = "project_backup_$date"
Copy-Item -Recurse my_cube $archiveName
ls -n

PowerShell — Lesson 3: Input, Output, and Piping

Fix the Code (Questions 1–5)

Q1. The user wants to append a second line to a file without destroying the first. The operator is wrong.

echo "Line 1" > notes.txt
echo "Line 2" > notes.txt

Q2. This pipe should filter to only lines containing “error” but uses the wrong PowerShell command.

cat build_log.txt | grep "error"

Q3. The script is supposed to copy file contents to the Windows clipboard but uses the wrong pipe target.

cat notes.txt | clipboard

Q4. This pipe chain should count the number of .scad files, but the counting command is wrong.

ls -n *.scad | Measure-Lines

Q5. The output redirection is supposed to save 3dm info output for review, but the file path uses a wrong separator and the command name is incorrect.

3dm information > build\info_report.txt
notepad.exe build\info_report.txt

Comment the Code (Questions 6–10)

Q6. Add comments explaining the difference between > and >> in each line.

echo "Project: my_cube" > log.txt
echo "Build started" >> log.txt
echo "Build complete" >> log.txt
cat log.txt

Q7. Add comments to this pipe chain explaining each stage of the pipeline.

ls -n | findstr ".scad" | Out-File scad_files.txt
cat scad_files.txt

Q8. Add comments explaining why each step of this screen-reader output workflow is used.

3dm build
3dm info > model_report.txt
notepad.exe model_report.txt

Q9. Add comments to this pipe-and-filter sequence used to search build logs.

cat build_log.txt | findstr "ERROR"
cat build_log.txt | findstr "ERROR" > errors_only.txt
cat build_log.txt | findstr "ERROR" | clip

Q10. Add comments to this combined input/output script.

echo "width=50" > params.txt
echo "height=30" >> params.txt
echo "wall=2.5" >> params.txt
cat params.txt
cat params.txt | clip

PowerShell — Lesson 4: Environment Variables, PATH, and Aliases

Fix the Code (Questions 1–5)

Q1. The user tries to create a permanent alias but uses the wrong scope.

Set-Alias -Name preview -Value openscad -Scope Global

(Hint: for persistence across sessions, the alias must be stored somewhere specific.)

Q2. This script sets an environment variable but uses the wrong syntax.

$env:PROJECT_DIR = ~/Documents/3d_projects

Q3. The script checks whether openscad is on the PATH, but uses the wrong command.

locate openscad

Q4. The user tries to add a directory to PATH but the concatenation operator is wrong.

$env:PATH = $env:PATH : "C:\Tools\openscad"

Q5. This alias definition has the wrong cmdlet name for creating aliases.

New-Variable -Name "build" -Value "3dm build"

Comment the Code (Questions 6–10)

Q6. Add comments explaining what each environment variable does and when you would set it.

$env:PROJECT_DIR = "$HOME\Documents\3d_projects"
$env:OPENSCAD_PATH = "C:\Program Files\OpenSCAD"
$env:PATH += ";$env:OPENSCAD_PATH"

Q7. Add comments to this alias-creation and verification sequence.

Set-Alias -Name build -Value "3dm"
Set-Alias -Name preview -Value openscad
Get-Alias build
Get-Alias preview

Q8. Add comments explaining each line of this PATH diagnostic script.

$env:PATH -split ";"
Get-Command openscad
Get-Command 3dm
(Get-Command openscad).Source

Q9. Add comments to this profile-editing sequence.

$PROFILE
Test-Path $PROFILE
New-Item -Path $PROFILE -Force
notepad.exe $PROFILE

Q10. Add comments explaining what each line of this environment-setup block (meant to go in a profile) does.

Set-Alias build "3dm build"
$env:PROJECT_DIR = "$HOME\Documents\3d_projects"
function go-projects { Set-Location $env:PROJECT_DIR }
Write-Host "3D printing environment loaded."

PowerShell — Lesson 5: Profiles and History

Fix the Code (Questions 1–5)

Q1. The command to recall the 5th entry from history is wrong.

Get-History | Select -Index 5

Q2. The user wants to re-execute the last command from history. The command is wrong.

Invoke-Command -History -1

Q3. This script is supposed to search history for all commands containing “build” but the search syntax is wrong.

Get-History | Where-Object { $_.Command = "build" }

Q4. The profile path check uses the wrong variable name.

Test-Path $MYPROFILE
notepad.exe $MYPROFILE

Q5. This history-export script saves to a file but uses the wrong cmdlet for writing text.

Get-History | ForEach-Object { $_.CommandLine } | Write-File history_log.txt

Comment the Code (Questions 6–10)

Q6. Add comments to this history-recall workflow.

Get-History
Get-History | Select-Object -Last 10
Invoke-History 15
Get-History | Where-Object { $_.CommandLine -like "*build*" }

Q7. Add comments to this profile-loading sequence.

$PROFILE
Test-Path $PROFILE
. $PROFILE
Get-Alias build

Q8. Add comments explaining this screen-reader troubleshooting sequence.

3dm build > build_output.txt 2>&1
notepad.exe build_output.txt
3dm info > info_output.txt
notepad.exe info_output.txt

Q9. Add comments to this combined history-and-profile management script.

Get-History | Export-Csv -Path history_backup.csv -NoTypeInformation
notepad.exe $PROFILE
. $PROFILE
Get-History | Select-Object -Last 5

Q10. Add comments explaining each function in this profile snippet.

function build-project {
    Set-Location $env:PROJECT_DIR
    3dm build
    3dm info > build_report.txt
    notepad.exe build_report.txt
}

function new-project($name) {
    mkdir "$env:PROJECT_DIR\$name"
    Set-Location "$env:PROJECT_DIR\$name"
    3dm new
}

PowerShell — Lesson 6: Scripts, Functions, and Professional Workflows

Fix the Code (Questions 1–5)

Q1. This script should loop over all .scad files and print their names, but the loop variable and iteration syntax are wrong.

$files = ls -n *.scad
for $file in $files {
    Write-Output $file
}

Q2. The function definition is missing the param block syntax, making parameters inaccessible.

function Process-Project {
    $projectPath = $args[0]
    Set-Location $projectPath
    3dm build
}

(Hint: $args works but is fragile — the function should declare a named parameter.)

Q3. This try/catch block will never catch anything because the error action preference is wrong.

$ErrorActionPreference = "Continue"
try {
    3dm build
    if ($LASTEXITCODE -ne 0) { throw "Build failed" }
} catch {
    Write-Output "Error: $_"
}

Q4. The batch processing script creates output filenames but uses the wrong string interpolation.

$widths = @(60, 80, 100)
foreach ($w in $widths) {
    $outFile = "build/bracket_w" + w + ".stl"
    openscad -D "width=$w" -o $outFile src/main.scad
}

Q5. The execution policy override is set at the wrong scope — it changes the machine-wide policy instead of just the current process.

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine
.\build-all.ps1

Comment the Code (Questions 6–10)

Q6. Add comments to this complete batch-build script explaining every significant block.

param(
    [string]$ProjectsDir = "$HOME\Documents\3d_projects"
)

$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$logFile = "build_$timestamp.log"

Get-ChildItem -Path $ProjectsDir -Directory | ForEach-Object {
    $project = $_.FullName
    $name = $_.Name
    Write-Host "Processing: $name"
    Set-Location $project
    $output = & 3dm build slice 2>&1
    if ($LASTEXITCODE -eq 0) {
        Write-Host "  OK"
        & 3dm print
    } else {
        Write-Host "  FAILED"
        $output | Out-File "build_error.txt"
    }
}
Write-Host "Batch complete."

Q7. Add comments to this parameterized function.

function Build-Variant {
    param(
        [string]$ScadFile,
        [int]$Width,
        [double]$Wall,
        [string]$OutputDir = "build/variants"
    )
    $name = "model_w${Width}_wall${Wall}"
    $out  = "$OutputDir\${name}.stl"
    openscad -D "width=$Width" -D "wall=$Wall" -o $out $ScadFile
    if ($LASTEXITCODE -eq 0) {
        Write-Host "Built: $out"
    } else {
        Write-Host "FAILED: $name"
    }
}

Q8. Add comments to this error-handling and logging block.

$ErrorActionPreference = "Stop"
try {
    3dm build
    if ($LASTEXITCODE -ne 0) { throw "OpenSCAD returned $LASTEXITCODE" }
    $stlSize = (Get-Item "build\main.stl").Length
    if ($stlSize -lt 1000) { Write-Warning "STL suspiciously small: $stlSize bytes" }
    Write-Host "Build OK: $stlSize bytes"
} catch {
    Write-Host "Build failed: $_"
    exit 1
}

Q9. Add comments to this nested loop variant generator.

$widths = @(60, 80, 100, 120)
$walls  = @(1.2, 1.6, 2.0)
$ok = 0; $fail = 0

foreach ($w in $widths) {
    foreach ($wt in $walls) {
        $name = "bracket_w${w}_wall${wt}"
        $out  = "build\variants\${name}.stl"
        openscad -D "width=$w" -D "wall=$wt" -o $out src\main.scad 2>$null
        if ($LASTEXITCODE -eq 0) { $ok++ } else { $fail++ }
    }
}
Write-Host "Done: $ok succeeded, $fail failed"

Q10. Add comments to this complete project-setup function.

function New-PrintProject {
    param([string]$Name)
    $base = "$env:PROJECT_DIR\$Name"
    if (Test-Path $base) {
        Write-Warning "Project already exists: $base"
        return
    }
    New-Item -ItemType Directory -Path $base | Out-Null
    Set-Location $base
    3dm new
    Write-Host "Project created: $base"
    ls -n
}

PART 2 — Windows Command Prompt (CMD)


CMD — Lesson Pre: Your First Terminal

Fix the Code (Questions 1–5)

Q1. These two commands should show the current location and list files, but both commands are wrong for CMD.

pwd
ls

Q2. The user wants to create a file with content and then read it back. Both commands are wrong for CMD.

echo "Hello CMD" >> hello.txt
cat hello.txt

Q3. The user tries to open a file in Notepad but uses the wrong separator.

notepad hello/txt

Q4. The user wants to go up one level and confirm the new location. The go-up sequence is correct but the confirmation command is wrong.

cd ..
pwd

Q5. The long-output management command is wrong — less is not available in CMD.

dir /B | less

Comment the Code (Questions 6–10)

Q6. Add comments to every line explaining what it does in CMD.

cd
dir /B
cd Documents
cd
dir /B

Q7. Add comments to this file-creation and reading workflow.

echo Hello, Command Prompt! > hello.txt
type hello.txt
notepad.exe hello.txt

Q8. Add comments explaining each step of this output-redirection workflow.

dir /B > list.txt
notepad.exe list.txt
dir /B | findstr "scad"

Q9. Add comments explaining what each keyboard shortcut does for screen reader users.

REM Up Arrow
REM Down Arrow
REM Tab
REM Ctrl+C
REM cls (type and press Enter)

Q10. Add comments to this tab-completion demonstration.

cd Doc
dir /B
cd ..
cd Down

(Note: lines 1 and 4 show partial paths where Tab would be pressed.)


CMD — Lesson 0: Getting Started

Fix the Code (Questions 1–5)

Q1. The path to navigate to Documents uses the wrong separator for CMD.

cd C:/Users/Student/Documents

Q2. The user tries to list files and filter for .scad files using a Linux command.

dir /B | grep "scad"

Q3. The script tries to return to the home directory using the wrong variable.

cd $HOME

Q4. The 3DMake project initialization uses the wrong command name.

mkdir %USERPROFILE%\Documents\3d_projects\my_cube
cd %USERPROFILE%\Documents\3d_projects\my_cube
3dm init

Q5. The user tries to list only directory names using a flag that doesn’t exist in CMD.

dir /B /dirs

Comment the Code (Questions 6–10)

Q6. Add comments explaining the CMD path conventions shown in each line.

cd %USERPROFILE%
cd Documents
cd ..\Downloads
cd C:\Users\Student\Documents
cd

Q7. Add comments to this 3DMake quick-start sequence for CMD.

cd %USERPROFILE%\Downloads\3dmake
3dm setup
mkdir %USERPROFILE%\Documents\3d_projects
mkdir %USERPROFILE%\Documents\3d_projects\my_cube
cd %USERPROFILE%\Documents\3d_projects\my_cube
3dm new
dir /B

Q8. Add comments explaining each filter pattern used in these dir commands.

dir /B *.scad
dir /B *.stl
dir /B project?.scad
dir /B *_final*

Q9. Add comments to this prompt-orientation reference.

REM C:\Users\Student>
cd
dir /B
cd ..
cd

Q10. Add comments explaining every line of this screen-reader-first file listing workflow.

dir /B > list.txt
notepad.exe list.txt
dir /B | findstr /R "\.scad$"
dir /B | findstr /R "\.scad$" > scad_list.txt
notepad.exe scad_list.txt

CMD — Lesson 1: Navigation

Fix the Code (Questions 1–5)

Q1. The script should navigate into a nested folder and verify the result, but the verification command is wrong.

cd Documents\3d_projects\my_cube
pwd

Q2. The user tries to navigate to a folder with a space in its name but the command will fail.

cd My Projects

Q3. The wildcard syntax for listing .stl files is wrong for CMD.

dir /B /.stl

Q4. The script tries to search all subdirectories for .scad files but uses the wrong flag.

dir /B /R *.scad

Q5. The cd command at the end should return to the home directory, but the syntax is wrong for CMD.

cd Documents
dir /B
cd ~

Comment the Code (Questions 6–10)

Q6. Add comments explaining each navigation step and what to expect.

cd %USERPROFILE%
cd Documents
cd 3d_projects
dir /B /A:D
cd my_cube
dir /B

Q7. Add comments to this deep-navigation and backtrack sequence.

cd Documents\3d_projects\my_cube\src
cd
dir /B
cd ..\..
cd

Q8. Add comments explaining what each line does in this project-exploration script.

cd %USERPROFILE%\Documents\3d_projects\my_cube
dir /B
dir /B src
dir /B build
dir /B build\*.stl

Q9. Add comments explaining the wildcard patterns used in each listing.

dir /B *.scad
dir /B model?.scad
dir /B *_v[0-9].*
dir /B *backup*

Q10. Add comments to this screen-reader navigation audit trail script.

cd
dir /B > location_check.txt
cd Documents
cd >> location_check.txt
dir /B >> location_check.txt
notepad.exe location_check.txt

CMD — Lesson 2: File and Folder Manipulation

Fix the Code (Questions 1–5)

Q1. The user wants to copy an entire folder tree, but the /E and /I flags are missing.

xcopy source_folder destination_folder

Q2. The file deletion command will not ask for confirmation, which is dangerous here. The /Q flag should not be present.

del /Q *.scad

Q3. The user tries to rename a file using a command that doesn’t exist in CMD.

rename old_name.scad new_name.scad

(Hint: check the exact CMD command name.)

Q4. This safe-deletion sequence is in the wrong order.

del *.tmp
dir /B *.tmp

Q5. The command to remove a folder and all its contents is missing the required flags.

rmdir old_project

Comment the Code (Questions 6–10)

Q6. Add comments explaining each file-operation command.

echo content > file1.txt
copy file1.txt file1_backup.txt
move file1.txt archive\file1.txt
dir /B

Q7. Add comments to this project-backup workflow.

mkdir backup
copy *.scad backup\
dir /B backup\
dir /B *.scad

Q8. Add comments explaining the safe-deletion pattern.

dir /B *.tmp
dir /B *.tmp | find /c ""
del *.tmp
dir /B *.tmp

Q9. Add comments to this folder-structure creation script.

mkdir 3DProjects
cd 3DProjects
mkdir Models
mkdir Prints
mkdir Docs
mkdir Backups
dir /B /A:D

Q10. Add comments to this project-archiving script.

for /f "tokens=1-3 delims=/ " %%a in ("%date%") do set TODAY=%%c%%a%%b
mkdir archive_%TODAY%
xcopy /E /I my_cube archive_%TODAY%\my_cube
dir /B

CMD — Lesson 3: Input, Output, and Piping

Fix the Code (Questions 1–5)

Q1. The user wants to append to a log file, but the first line overwrites the file.

echo Build started > build_log.txt
echo Build complete > build_log.txt
type build_log.txt

Q2. The pipe destination for copying to the Windows clipboard is wrong.

type notes.txt | copy

Q3. The findstr command is supposed to be case-insensitive but is missing the correct flag.

type build_log.txt | findstr "error"

Q4. This chain should count the number of .scad files but uses the wrong counting syntax.

dir /B *.scad | find /v ""

(Hint: check the find flags for counting lines.)

Q5. The script should search a file for a keyword and save the results, but the command for reading a file in CMD is wrong.

cat build_log.txt | findstr "FAILED" > errors.txt

Comment the Code (Questions 6–10)

Q6. Add comments explaining the difference between > and >> in each line.

echo Project: my_cube > log.txt
echo Build started >> log.txt
echo Build complete >> log.txt
type log.txt

Q7. Add comments to this pipe chain.

dir /B *.scad | findstr "main"
dir /B *.scad | find /c "" 
dir /B | findstr /R "\.scad$" > scad_list.txt

Q8. Add comments explaining each step of this build-and-verify workflow.

3dm build > build_output.txt 2>&1
type build_output.txt
3dm info > info_report.txt
notepad.exe info_report.txt

Q9. Add comments explaining this clipboard workflow for screen readers.

dir /B | clip
type notes.txt | clip
dir /B *.scad | clip

Q10. Add comments to this multi-step log-building script.

echo === Build Log === > full_log.txt
echo Date: %date% >> full_log.txt
echo Time: %time% >> full_log.txt
3dm build >> full_log.txt 2>&1
3dm info >> full_log.txt
notepad.exe full_log.txt

CMD — Lesson 4: Environment Variables, PATH, and Aliases (DOSKEY)

Fix the Code (Questions 1–5)

Q1. The user tries to set a persistent environment variable using the wrong command.

set PROJECT_DIR=C:\Users\Student\Documents\3d_projects

(Hint: set only persists for the current session.)

Q2. The DOSKEY alias definition has a wrong syntax for passing arguments.

doskey build=3dm build $1

Q3. The script tries to print an environment variable but uses the wrong syntax.

echo $PROJECT_DIR

Q4. The user wants to check where openscad is installed, but uses a Linux command.

which openscad

Q5. The PATH modification syntax is wrong — the semicolon and concatenation are missing.

set PATH=%PATH% C:\Tools\OpenSCAD

Comment the Code (Questions 6–10)

Q6. Add comments explaining each variable-setting command and its scope.

set MY_VAR=hello
setx MY_VAR hello
set MY_VAR
echo %MY_VAR%

Q7. Add comments to this DOSKEY alias setup.

doskey ls=dir /B $*
doskey cat=type $1
doskey build=3dm build $*
doskey info=3dm info $*

Q8. Add comments explaining this PATH diagnostic sequence.

echo %PATH%
where openscad
where 3dm
openscad --version

Q9. Add comments to this environment-variable usage script.

set PROJECT_DIR=%USERPROFILE%\Documents\3d_projects
cd %PROJECT_DIR%
dir /B
echo %PROJECT_DIR%

Q10. Add comments explaining the purpose of each block in this persistent-environment-setup script.

setx PROJECT_DIR "%USERPROFILE%\Documents\3d_projects"
setx OPENSCAD_PATH "C:\Program Files\OpenSCAD"
set PATH=%PATH%;%OPENSCAD_PATH%
where openscad
echo Setup complete.

CMD — Lesson 5: Startup Scripts, History, and Useful Tricks

Fix the Code (Questions 1–5)

Q1. The history popup shortcut is wrong — the user pressed the wrong function key.

REM Press F6 to open the command history popup

Q2. The DOSKEY macro file is loaded with the wrong flag.

doskey /load macros.txt

Q3. The script tries to re-run the previous command automatically, but the syntax is wrong.

doskey /history | tail -1 | cmd

Q4. The AUTORUN registry key path is misspelled, so the startup script will not load.

reg add "HKCU\Software\Microsoft\Command Processer" /v AutoRun /t REG_SZ /d "%USERPROFILE%\cmd_startup.bat"

Q5. This startup script tries to set an alias at launch but uses the wrong command name.

@echo off
alias build=3dm build
echo CMD environment loaded.

Comment the Code (Questions 6–10)

Q6. Add comments to this history-recall reference.

REM F7 key
REM F8 key
REM doskey /history
doskey /history > history_log.txt
notepad.exe history_log.txt

Q7. Add comments explaining each line of this startup script (cmd_startup.bat).

@echo off
doskey ls=dir /B $*
doskey cat=type $1
doskey build=3dm build $*
set PROJECT_DIR=%USERPROFILE%\Documents\3d_projects
echo CMD environment ready. Project dir: %PROJECT_DIR%

Q8. Add comments to this screen-reader output-management sequence.

3dm build > build_out.txt 2>&1
if %errorlevel% neq 0 (
    echo BUILD FAILED >> build_out.txt
)
notepad.exe build_out.txt

Q9. Add comments explaining each step of this macro-persistence workflow.

doskey build=3dm build $*
doskey /macros > macros.txt
notepad.exe macros.txt
doskey /macrofile=macros.txt

Q10. Add comments to this end-of-session cleanup and log script.

3dm info > session_report.txt
echo Session ended: %date% %time% >> session_report.txt
doskey /history >> session_report.txt
notepad.exe session_report.txt

CMD — Lesson 6: Batch Scripts, Subroutines, and Professional Workflows

Fix the Code (Questions 1–5)

Q1. This batch script should loop over widths and build variants, but the loop variable syntax is wrong.

@echo off
for $WIDTH in (60 80 100 120) do (
    echo Building width: %WIDTH%
    openscad -D "width=%WIDTH%" -o build\bracket_%WIDTH%.stl src\main.scad
)

Q2. The error-check after running openscad uses the wrong variable.

openscad -o build\main.stl src\main.scad
if %exitcode% neq 0 echo BUILD FAILED

Q3. The subroutine call is missing the call keyword, so the script will exit after the subroutine.

@echo off
:main
echo Starting build...
:build_project
    3dm build
    goto :eof

(Hint: :build_project needs to be invoked correctly.)

Q4. The setlocal / endlocal block is in the wrong order, so local variables leak out.

@echo off
set TEMP_VAR=hello
setlocal
echo %TEMP_VAR%
endlocal

Q5. This script saves the ERRORLEVEL but uses the wrong syntax to capture it.

3dm build
set BUILD_RESULT = %errorlevel%
if %BUILD_RESULT% neq 0 echo Build failed with code %BUILD_RESULT%

Comment the Code (Questions 6–10)

Q6. Add comments to every significant line of this batch build script.

@echo off
setlocal enabledelayedexpansion
set OUTPUT_DIR=build\variants
if not exist %OUTPUT_DIR% mkdir %OUTPUT_DIR%
set SUCCESS=0
set FAIL=0
for %%W in (60 80 100 120) do (
    for %%T in (1.2 1.6 2.0) do (
        set NAME=bracket_w%%W_wall%%T
        openscad -D "width=%%W" -D "wall=%%T" -o "%OUTPUT_DIR%\!NAME!.stl" src\main.scad
        if !errorlevel! equ 0 (
            set /a SUCCESS+=1
        ) else (
            set /a FAIL+=1
        )
    )
)
echo Done: %SUCCESS% succeeded, %FAIL% failed
endlocal

Q7. Add comments to this subroutine-based build script.

@echo off
call :log "Build started"
call :build_step
call :verify_step
call :log "Build finished"
goto :eof

:log
echo [%time%] %~1 >> build_log.txt
goto :eof

:build_step
3dm build >> build_log.txt 2>&1
if %errorlevel% neq 0 ( echo FAILED >> build_log.txt & exit /b 1 )
goto :eof

:verify_step
3dm info >> build_log.txt
goto :eof

Q8. Add comments explaining each block of this error-handling script.

@echo off
3dm build > build_out.txt 2>&1
set BUILD_CODE=%errorlevel%
if %BUILD_CODE% neq 0 (
    echo Build failed with code %BUILD_CODE%
    type build_out.txt
    exit /b %BUILD_CODE%
)
for %%F in (build\main.stl) do set STL_SIZE=%%~zF
if %STL_SIZE% lss 1000 echo WARNING: STL file very small: %STL_SIZE% bytes
echo Build OK: %STL_SIZE% bytes

Q9. Add comments to this parameterized batch-project setup script.

@echo off
set NAME=%1
if "%NAME%"=="" ( echo Usage: new_project.bat project_name & exit /b 1 )
set BASE=%USERPROFILE%\Documents\3d_projects\%NAME%
if exist "%BASE%" ( echo Already exists: %BASE% & exit /b 1 )
mkdir "%BASE%"
cd /d "%BASE%"
3dm new
echo Project created: %BASE%
dir /B

Q10. Add comments explaining every section of this variant-archive script.

@echo off
for /f "tokens=1-3 delims=/ " %%a in ("%date%") do (
    set TODAY=%%c%%a%%b
)
set ARCHIVE=build\archive_%TODAY%
mkdir %ARCHIVE%
for %%F in (build\variants\*.stl) do (
    copy "%%F" "%ARCHIVE%\%%~nxF" > nul
)
echo Archived to: %ARCHIVE%
dir /B %ARCHIVE%

PART 3 — Git Bash


Git Bash — Lesson Pre: Your First Terminal

Fix the Code (Questions 1–5)

Q1. The user tries to print the current directory and list files, but one command is wrong for Git Bash.

pwd
dir

Q2. The screen-reader–friendly listing command uses the wrong flag (letter L instead of number 1).

ls -l

(Note: this produces detail output, not the one-per-line names-only format.)

Q3. The user wants to create a file and read it back, but uses the CMD-style read command.

echo "Hello Git Bash" > hello.txt
type hello.txt

Q4. The user wants to navigate home and verify, but uses the wrong home-navigation command.

cd /home
pwd

Q5. The long-output pagination command is wrong for Git Bash.

ls -1 | more

(Hint: Git Bash uses a different pager than CMD.)


Comment the Code (Questions 6–10)

Q6. Add comments explaining every command in this first-session orientation.

pwd
ls -1
cd Documents
pwd
ls -1
cd ~
pwd

Q7. Add comments to this file-creation and reading workflow.

echo "Hello, Git Bash!" > hello.txt
cat hello.txt
echo "Line 2" >> hello.txt
cat hello.txt

Q8. Add comments explaining the output-redirection strategy for screen reader users.

ls -1 > file_list.txt
notepad.exe file_list.txt
ls -1 | grep "scad"

Q9. Add comments to this keyboard-shortcut reference for Git Bash.

# Up Arrow
# Down Arrow
# Tab
# Ctrl+C
# Ctrl+R

Q10. Add comments to this tab-completion demonstration.

cd ~/Doc
ls -1
cd ~
cd ~/Down

(Note: lines 1 and 4 show partial paths where Tab would be pressed.)


Git Bash — Lesson 0: Getting Started

Fix the Code (Questions 1–5)

Q1. Git Bash uses Unix-style paths, but this navigation uses a Windows-style path.

cd C:\Users\Student\Documents

Q2. The listing command uses the wrong flag — letter L instead of number 1.

ls -l

Q3. The script should go up one level and then back home, but both navigation commands are wrong.

cd ../
cd /home/student

Q4. The 3DMake project creation sequence uses the wrong path expansion variable.

mkdir %USERPROFILE%/Documents/3d_projects/my_cube
cd %USERPROFILE%/Documents/3d_projects/my_cube
3dm new

Q5. The user wants to list hidden files along with regular files, but uses the wrong flag.

ls -1 -h

Comment the Code (Questions 6–10)

Q6. Add comments explaining each path shortcut.

cd ~
cd ./subfolder
cd ../
cd -
cd /c/Users/Student/Documents

Q7. Add comments to this 3DMake quick-start sequence.

cd ~/Downloads/3dmake
./3dm setup
mkdir -p ~/Documents/3d_projects/my_cube
cd ~/Documents/3d_projects/my_cube
3dm new
ls -1

Q8. Add comments explaining what each line of the prompt anatomy reference means.

# student@LAPTOP MINGW64 ~/Documents/3d_projects $
pwd
ls -1
cd ..
pwd

Q9. Add comments to this path-comparison demonstration.

pwd
cd /c/Users/Student/Documents/3d_projects
pwd
cd ~
pwd
cd Documents/3d_projects
pwd

Q10. Add comments explaining every line of this screen-reader-first listing workflow.

ls -1 > list.txt
notepad.exe list.txt
ls -1 | grep "scad"
ls -1 | grep "scad" > scad_list.txt
notepad.exe scad_list.txt

Git Bash — Lesson 1: Navigation

Fix the Code (Questions 1–5)

Q1. The wildcard pattern for listing .scad files is wrong for Git Bash.

ls -1 *.scad
ls -1 | grep /.scad/

(The first line is correct — identify the error in the second line.)

Q2. The script should list only directories. The flag used is wrong for Git Bash.

ls -1 /A:D

Q3. The find command should search recursively for .scad files but uses wrong syntax.

find . -name "*.scad" -type d

Q4. The script saves a listing and opens it, but uses the wrong open command.

ls -1 > list.txt
open list.txt

Q5. The recursive search for all STL files uses the wrong wildcard.

ls -1 build/%.stl

Comment the Code (Questions 6–10)

Q6. Add comments to this navigation and listing sequence.

pwd
cd ~/Documents/3d_projects
ls -1
cd my_cube
ls -1
cd src
ls -1 *.scad
cd ~

Q7. Add comments explaining each wildcard pattern.

ls -1 *.scad
ls -1 model?.scad
ls -1 *_v[0-9].*
ls -1 *_final*

Q8. Add comments to this project-exploration script.

cd ~/Documents/3d_projects/my_cube
pwd
ls -1
ls -1 src/
ls -1 build/
ls -1 build/*.stl

Q9. Add comments explaining this screen-reader listing workflow.

ls -1 > all_files.txt
ls -1 *.scad > scad_files.txt
ls -1 -d */ > dirs_only.txt
notepad.exe all_files.txt

Q10. Add comments explaining what find does in each variation.

find . -name "*.scad"
find . -name "*.scad" -type f
find ~/Documents/3d_projects -name "*.stl"
find . -name "*.scad" > scad_paths.txt

Git Bash — Lesson 2: File and Folder Manipulation

Fix the Code (Questions 1–5)

Q1. The command to recursively copy a folder is missing the required flag.

cp my_cube my_cube_backup

Q2. The user deletes a folder but uses the wrong command for Git Bash.

rmdir /S /Q old_project

Q3. The script creates a file, but uses the CMD command instead of the Git Bash equivalent.

echo. > empty_file.txt

Q4. The safe-deletion sequence is out of order — files are deleted before verification.

rm *.tmp
ls -1 *.tmp

Q5. The move command renames a file but uses the wrong command for Git Bash.

ren old_name.scad new_name.scad

Comment the Code (Questions 6–10)

Q6. Add comments to this file-creation and manipulation sequence.

touch design.scad
cp design.scad design_backup.scad
mv design.scad archive/design_v1.scad
ls -1

Q7. Add comments to this project-backup workflow.

cd ~/Documents/3d_projects
cp -r my_cube my_cube_backup
ls -1
cd my_cube_backup
ls -1

Q8. Add comments explaining the safe-deletion pattern.

ls -1 *.tmp
rm *.tmp
ls -1 *.tmp

Q9. Add comments to this folder-structure creation script.

mkdir -p 3DProjects/{Models,Prints,Docs,Backups}
ls -1 3DProjects/
ls -1 -d 3DProjects/*/

Q10. Add comments explaining every operation in this 3DMake project-management script.

mkdir -p ~/Documents/3d_projects/bottle_cap
cd ~/Documents/3d_projects/bottle_cap
3dm new
cd ~/Documents/3d_projects
cp -r bottle_cap bottle_cap_backup
cd bottle_cap/src
mv main.scad bottle_cap.scad
ls -1 *.scad

Git Bash — Lesson 3: Input, Output, and Piping

Fix the Code (Questions 1–5)

Q1. The second line overwrites the log instead of appending to it.

echo "Build started" > build_log.txt
echo "Build complete" > build_log.txt
cat build_log.txt

Q2. The pipe destination for the Windows clipboard is wrong for Git Bash on Windows.

cat notes.txt | clipboard

Q3. This grep command should be case-insensitive but is missing the flag.

cat build_log.txt | grep "error"

Q4. The command counts lines but uses the wrong utility for Git Bash.

ls -1 *.scad | find /c ""

Q5. This script reads a file and searches it, but uses the CMD-style read command.

type build_log.txt | grep "FAILED"

Comment the Code (Questions 6–10)

Q6. Add comments explaining the difference between > and >>.

echo "Project: my_cube" > log.txt
echo "Build started" >> log.txt
echo "Build complete" >> log.txt
cat log.txt

Q7. Add comments to this pipe chain.

ls -1 *.scad | grep "main"
ls -1 *.scad | wc -l
ls -1 | grep ".stl" > stl_list.txt

Q8. Add comments to this build-and-verify workflow.

3dm build
3dm info > model_report.txt
notepad.exe model_report.txt
cat model_report.txt | grep "Bounding"

Q9. Add comments explaining this clipboard workflow.

ls -1 | clip
cat notes.txt | clip
ls -1 *.scad | clip

Q10. Add comments to this multi-step log-building script.

echo "=== Build Log ===" > full_log.txt
echo "Date: $(date)" >> full_log.txt
3dm build >> full_log.txt 2>&1
3dm info >> full_log.txt
notepad.exe full_log.txt

Git Bash — Lesson 4: Environment Variables, PATH, and Aliases

Fix the Code (Questions 1–5)

Q1. The alias is created, but changes will be lost when the terminal is closed. Where should this line go to persist?

alias build="3dm build"

(Hint: identify where this line must be saved for persistence — this is a conceptual fix; write the corrected workflow, not just the line.)

Q2. The variable is set but the export is missing, so child processes won’t see it.

PROJECT_DIR="$HOME/Documents/3d_projects"

Q3. The PATH modification uses the wrong separator.

export PATH="$PATH;/c/Program Files/OpenSCAD"

Q4. The which command is used correctly but source is used wrong to reload .bashrc.

which openscad
reload ~/.bashrc

Q5. The variable reference uses wrong shell syntax.

export LABEL_FONT="Liberation Sans"
echo %LABEL_FONT%

Comment the Code (Questions 6–10)

Q6. Add comments explaining each line of this environment-setup block.

export PROJECT_DIR="$HOME/Documents/3d_projects"
export OPENSCAD_PATH="/c/Program Files/OpenSCAD"
export PATH="$PATH:$OPENSCAD_PATH"

Q7. Add comments to this alias-creation and verification sequence.

alias build="3dm build"
alias info="3dm info"
alias preview="3dm preview"
alias ls1="ls -1"

Q8. Add comments explaining this PATH diagnostic script.

echo $PATH | tr ':' '\n'
which openscad
which 3dm
openscad --version

Q9. Add comments to this .bashrc-editing sequence.

cat ~/.bashrc
echo 'alias build="3dm build"' >> ~/.bashrc
echo 'export PROJECT_DIR="$HOME/Documents/3d_projects"' >> ~/.bashrc
source ~/.bashrc
alias build

Q10. Add comments explaining each function and variable in this environment block (intended for .bashrc).

export PROJECT_DIR="$HOME/Documents/3d_projects"
alias build="3dm build"
alias info="3dm info"
function go-projects() { cd "$PROJECT_DIR"; }
function new-project() { mkdir -p "$PROJECT_DIR/$1" && cd "$PROJECT_DIR/$1" && 3dm new; }
echo "3D printing environment loaded."

Git Bash — Lesson 5: Shell Profiles, History, and Useful Tricks

Fix the Code (Questions 1–5)

Q1. The history search shortcut description is wrong.

# Press Ctrl+F to search command history interactively

Q2. The alias is added to the wrong profile file for Git Bash on Windows.

echo 'alias build="3dm build"' >> ~/.bash_profile

(Hint: on most Git Bash setups, interactive-shell configuration goes in the other file.)

Q3. The script re-runs the last command from history using the wrong syntax.

history | tail -1 | bash

Q4. The source command is used but the wrong file is sourced.

source ~/.bash_history

Q5. The history-export pipeline uses the wrong file-write command for bash.

history | Write-File history_log.txt

Comment the Code (Questions 6–10)

Q6. Add comments to this history-recall workflow.

history
history | tail -20
history | grep "build"
!build

Q7. Add comments explaining each step of this .bashrc-management workflow.

cat ~/.bashrc
notepad.exe ~/.bashrc
source ~/.bashrc
alias build
echo $PROJECT_DIR

Q8. Add comments to this screen-reader output-management sequence.

3dm build > build_out.txt 2>&1
cat build_out.txt | grep -i "error"
3dm info > info_out.txt
notepad.exe info_out.txt

Q9. Add comments explaining each control sequence.

# Ctrl+R — type to search
# Ctrl+C
# Ctrl+A
# Ctrl+E
# Ctrl+L

Q10. Add comments to this full environment-check script.

echo "Shell: $SHELL"
echo "Home: $HOME"
echo "Project dir: $PROJECT_DIR"
which openscad
which 3dm
alias | grep build
history | wc -l

Git Bash — Lesson 6: Shell Scripts, Functions, Loops

Fix the Code (Questions 1–5)

Q1. This shell script loops over widths and builds variants, but the loop syntax is wrong.

#!/bin/bash
for WIDTH in (60 80 100 120); do
    openscad -D "width=$WIDTH" -o "build/bracket_$WIDTH.stl" src/main.scad
    echo "Built width: $WIDTH"
done

Q2. The script uses set -e but the OpenSCAD error will be silently suppressed by the pipe.

#!/bin/bash
set -e
openscad -o build/main.stl src/main.scad | tee build_log.txt
echo "Build done"

(Hint: add the missing safety flag.)

Q3. The function is defined but the parameter is read using the wrong syntax.

#!/bin/bash
build_variant() {
    local width = $1
    openscad -D "width=$width" -o "build/variant_$width.stl" src/main.scad
}
build_variant 80

Q4. The script makes a file executable but uses the wrong command name.

#!/bin/bash
chown +x batch_build.sh
./batch_build.sh

Q5. The error-handling trap is syntactically wrong.

#!/bin/bash
set -e
trap "echo Build failed at line $LINENO" ERROR
3dm build
3dm info

Comment the Code (Questions 6–10)

Q6. Add comments to this complete batch-build script.

#!/bin/bash
set -e
set -u
set -o pipefail

OUTPUT_DIR="build/variants"
mkdir -p "$OUTPUT_DIR"

SUCCESS=0
FAIL=0

for WIDTH in 60 80 100 120; do
    for WALL in 1.2 1.6 2.0; do
        NAME="bracket_w${WIDTH}_wall${WALL/./_}"
        OUT="$OUTPUT_DIR/${NAME}.stl"
        if openscad -D "width=${WIDTH}" -D "wall=${WALL}" \
                    -o "$OUT" src/main.scad 2>/dev/null; then
            SUCCESS=$((SUCCESS + 1))
        else
            FAIL=$((FAIL + 1))
        fi
    done
done

echo "Done: $SUCCESS succeeded, $FAIL failed"

Q7. Add comments to this function-based build script.

#!/bin/bash
log() {
    local level="$1"; shift
    echo "[$(date +%H:%M:%S)] [$level] $*" | tee -a build_log.txt
}

build_project() {
    local project_dir="$1"
    cd "$project_dir"
    log "INFO" "Building: $(basename $project_dir)"
    if 3dm build > /dev/null 2>&1; then
        log "INFO" "OK"
        return 0
    else
        log "ERROR" "FAILED"
        return 1
    fi
}

for project in ~/Documents/3d_projects/*/; do
    build_project "$project"
done

Q8. Add comments to this error-handling script.

#!/bin/bash
set -e
set -u
set -o pipefail

on_error() {
    echo "ERROR at line $1"
    exit 1
}
trap 'on_error $LINENO' ERR

3dm build

STL="build/main.stl"
[ -f "$STL" ] || { echo "STL not created"; exit 1; }

SIZE=$(stat -c%s "$STL")
[ "$SIZE" -gt 1000 ] || echo "WARNING: small STL ($SIZE bytes)"

echo "Build OK: $SIZE bytes"
3dm info

Q9. Add comments to this string-parameter quoting demonstration.

#!/bin/bash
LABEL="FRONT PANEL"

openscad -D 'label="FRONT"' -o out1.stl src/main.scad
openscad -D "label=\"${LABEL}\"" -o out2.stl src/main.scad
echo "openscad -D 'label=\"${LABEL}\"' -o out3.stl src/main.scad"

Q10. Add comments to this complete project-setup script.

#!/bin/bash
set -e
NAME="$1"
BASE="$HOME/Documents/3d_projects/$NAME"

[ -n "$NAME" ] || { echo "Usage: $0 project_name"; exit 1; }
[ ! -d "$BASE" ] || { echo "Exists: $BASE"; exit 1; }

mkdir -p "$BASE"
cd "$BASE"
3dm new
echo "Created: $BASE"
ls -1

PART 4 — 3dMake / OpenSCAD Curriculum


3dMake — Lesson 1: Environmental Configuration and the Developer Workflow

Fix the Code (Questions 1–5)

Q1. This .scad file uses a raw number instead of a named parameter. Rewrite it so it is fully parametric.

cube([30, 20, 10]);

Q2. The verification command is wrong — the user types the wrong 3dm subcommand to get model dimensions.

3dm check

Q3. This OpenSCAD snippet violates the coordinate system: the cube is underground (extends below Z=0 without intent).

width = 30;
depth = 20;
height = 10;
cube([width, depth, height], center=true);

Q4. The cost-estimation formula has wrong unit conversions.

volume_mm3 = 6000
density = 1.24        # g/cm³
spool_price = 20      # dollars
spool_weight = 1000   # grams

mass = volume_mm3 * density         # ERROR: wrong unit conversion
cost = mass * (spool_price / spool_weight)
print(f"Mass: {mass:.2f} g, Cost: ${cost:.2f}")

Q5. The project initialization sequence uses the wrong directory for source files.

mkdir my_project
cd my_project
3dm new
# User's SCAD file should go here:
notepad.exe main.scad
3dm build

Comment the Code (Questions 6–10)

Q6. Add comments explaining every line of this parametric cube file.

width  = 30;
depth  = 20;
height = 10;

cube([width, depth, height]);

Q7. Add comments to this complete build-and-verify workflow script.

cd ~/Documents/3d_projects/my_cube
3dm build
3dm info
3dm info > model_report.txt
notepad.exe model_report.txt

Q8. Add comments explaining what each section of this installation script does (Linux/macOS).

curl -fsSL https://get.3dmake.dev | bash
3dm --version
openscad --version
mkdir -p ~/Documents/3d_projects/my_cube
cd ~/Documents/3d_projects/my_cube
3dm new
ls -1

Q9. Add comments explaining the FDM pipeline stages referenced in this parameter file.

// Stage 1 — parametric source
width  = 40;
depth  = 30;
height = 15;
infill = 20;        // percent
layer_h = 0.20;     // mm

// Stage 2 — geometry (STL)
cube([width, depth, height]);

Q10. Add comments to this cost-estimation calculation.

VOLUME=6000
DENSITY=1.24
SPOOL_PRICE=20
SPOOL_WEIGHT=1000

MASS=$(echo "scale=4; ($VOLUME / 1000) * $DENSITY" | bc)
COST=$(echo "scale=4; $MASS * ($SPOOL_PRICE / $SPOOL_WEIGHT)" | bc)
echo "Mass: ${MASS} g"
echo "Cost: \$${COST}"

3dMake — Lesson 2: Geometric Primitives and CSG

Fix the Code (Questions 1–5)

Q1. The difference() operation is missing the 0.001 mm offset rule. Add the correct offsets.

difference() {
  cube([20, 20, 10]);
  translate([10, 10, 0])
    cylinder(h=10, r=5, $fn=32);
}

Q2. The children are in the wrong order for difference() — the cutting tool is listed first.

difference() {
  cylinder(h=20, r=5, $fn=32);   // intended cutter
  cube([20, 20, 20]);             // intended base
}

Q3. The sphere is given an extremely low $fn value that will produce a faceted, unusable mesh for printing.

sphere(r=15, $fn=3);

Q4. The polygon() points are listed in clockwise order (will produce an inverted or empty shape). Correct the winding order.

linear_extrude(height=5)
  polygon([[0,30],[0,0],[40,0],[40,8],[8,8],[8,30]]);

Q5. The # debug modifier is left in the code before export. Identify and remove it.

difference() {
  cube([30, 30, 20]);
  # translate([15, 15, -0.001])
    cylinder(h=20.002, r=8, $fn=32);
}

Comment the Code (Questions 6–10)

Q6. Add comments explaining each primitive and its key parameters.

cube([30, 20, 10]);

translate([50, 0, 10])
  sphere(r=10, $fn=32);

translate([80, 0, 0])
  cylinder(h=20, r=8, $fn=32);

translate([110, 0, 0])
  cylinder(h=20, r1=10, r2=3, $fn=32);

Q7. Add comments to this difference() operation explaining each line’s purpose.

difference() {
  cube([20, 20, 20]);
  translate([10, 10, -0.001])
    cylinder(h=20.002, r=5, $fn=32);
}

Q8. Add comments explaining why the 0.001 offset is used and what each value means.

difference() {
  cube([20, 20, 10]);
  translate([1, 1, -0.001])
    cube([18, 18, 10.002]);
}

Q9. Add comments to this polygon() L-bracket extrusion.

bracket_profile = [
  [0,  0],
  [40, 0],
  [40, 8],
  [8,  8],
  [8,  30],
  [0,  30]
];

linear_extrude(height=5)
  polygon(bracket_profile);

Q10. Add comments explaining each debug modifier and when to use it.

difference() {
  cube([30, 30, 20]);

  # translate([15, 15, -0.001])
    cylinder(h=20.002, r=8, $fn=32);
}

% translate([0, 0, 20])
  cube([30, 30, 5]);

! sphere(r=10, $fn=32);

* cube([5, 5, 5]);

3dMake — Lesson 3: Parametric Architecture and Modular Libraries

Fix the Code (Questions 1–5)

Q1. This OpenSCAD code attempts to use Python-style variable reassignment, which doesn’t work in OpenSCAD. Rewrite it correctly.

x = 5;
x = x + 3;
cube([x, x, 5]);

Q2. The assert() call uses the wrong comparison — it accepts negative values.

module safe_box(w, d, h) {
  assert(w >= 0, "width must be non-negative");
  cube([w, d, h]);
}
safe_box(-10, 20, 5);

Q3. The module uses include to load a library when it should use use (the library file contains top-level test geometry that will pollute the scene).

include <../lib/hardware.scad>
mounting_hole(r=2, depth=5);

Q4. The DRY violation: the mounting hole is copy-pasted instead of using a module. Refactor it.

difference() {
  cube([60, 40, 5]);
  translate([5,  5,  -0.001]) cylinder(r=2, h=5.002, $fn=16);
  translate([55, 5,  -0.001]) cylinder(r=2, h=5.002, $fn=16);
  translate([5,  35, -0.001]) cylinder(r=2, h=5.002, $fn=16);
  translate([55, 35, -0.001]) cylinder(r=2, h=5.002, $fn=16);
}

Q5. The for loop uses wrong syntax for generating geometry in OpenSCAD.

for i in [0:3] {
  translate([i * 15, 0, 0])
    cylinder(r=3, h=10, $fn=16);
}

Comment the Code (Questions 6–10)

Q6. Add comments explaining OpenSCAD’s variable scoping rules as shown in this code.

x = 5;
echo("x =", x);
x = 10;

base_size   = 20;
padded_size = base_size + 10;
doubled     = base_size * 2;
echo(base_size, padded_size, doubled);

Q7. Add comments explaining every part of this validated module.

module safe_cylinder(r, h, fn=32) {
  assert(is_num(r) && r > 0,
    str("radius must be positive, got: ", r));
  assert(is_num(h) && h > 0,
    str("height must be positive, got: ", h));
  assert(fn >= 3,
    str("fn must be >= 3, got: ", fn));
  cylinder(r=r, h=h, $fn=fn);
}

Q8. Add comments to this DRY-compliant mounting hole module and its usage.

module mounting_hole(r=2, depth=5) {
  translate([0, 0, -0.001])
    cylinder(r=r, h=depth + 0.002, $fn=16);
}

difference() {
  cube([60, 40, 5]);
  translate([5,  5,  0]) mounting_hole();
  translate([55, 5,  0]) mounting_hole();
  translate([5,  35, 0]) mounting_hole();
  translate([55, 35, 0]) mounting_hole();
}

Q9. Add comments to this use vs include example showing correct library import.

use <../lib/hardware.scad>

mounting_hole(r=2, depth=5);
translate([20, 0, 0]) mounting_hole(r=3, depth=8);

Q10. Add comments explaining each line of this for-loop geometry generator.

for (i = [0:5]) {
  angle = i * 60;
  translate([cos(angle) * 25, sin(angle) * 25, 0])
    cylinder(r=3, h=5, $fn=16);
}

3dMake — Lesson 4: AI-Enhanced Verification and Multimodal Feedback

Fix the Code (Questions 1–5)

Q1. The verification sequence uses an AI description as the primary check instead of the deterministic bounding box. Rewrite it in the correct order.

3dm build
3dm info --view front
# Accept design if description says "looks like a bracket"
# Skip bounding box check

Q2. The 3dm info command is saved to a file using the wrong redirection for PowerShell.

3dm info > description.txt -Encoding UTF8

Q3. The AI code verification checklist is missing the 0.001 offset check. Add the missing item in the right position.

[ ] 1. SYNTAX — 3dm build compiles without error
[ ] 2. DIMENSIONS — bounding box matches design intent
[ ] 3. PARAMETER BEHAVIOR — test extreme values
[ ] 4. MANIFOLD CHECK — open in slicer, no errors
[ ] 5. PRINT FEASIBILITY — wall thickness >= 1.2mm

Q4. The verification log records an AI description as proof of precise dimensions. Correct the methodology.

Feature: USB-C slot
  Designed: 9.5mm wide × 3.5mm tall
  Verification: AI description says "rectangular cutout approximately 10mm wide" ✓
  Status: VERIFIED

Q5. The isolation technique for a complex model uses the wrong modifier to render only one module.

full_assembly();
% snap_clip();

Comment the Code (Questions 6–10)

Q6. Add comments explaining each 3dm info variant and when to use it.

3dm build
3dm info
3dm info --view front
3dm info --view top
3dm info --view isometric
3dm info --output description.txt

Q7. Add comments to this verification escalation chain.

3dm info
# Level 1 check passed — proceed to Level 2

# Open slicer manually on build/main.stl
# Step through layers looking for issues

# Level 2 check passed — proceed to Level 3

# Level 3: isolate module

Q8. Add comments explaining each step of this isolation-and-verify workflow.

// full_assembly();
// base_plate();
snap_clip();
3dm build
3dm info --view isometric
3dm info --view front

Q9. Add comments explaining the two types of output visible in this 3dm info result.

File:         build/main.stl
Bounding Box: 30.0 x 20.0 x 10.0 mm
Volume:       6000.0 mm³
Triangles:    12
Description:  A small rectangular box measuring 30mm wide by 20mm deep by 10mm tall.

Q10. Add comments to this AI code verification checklist explaining why each check exists.

[ ] 1. SYNTAX
[ ] 2. DIMENSIONS
[ ] 3. BOOLEAN OPERATIONS — check every difference() for 0.001 offset
[ ] 4. PARAMETER BEHAVIOR — test extreme values
[ ] 5. MANIFOLD CHECK
[ ] 6. PRINT FEASIBILITY

3dMake — Lesson 5: Safety, Filaments, and Print Environment

Fix the Code (Questions 1–5)

Q1. The cost-estimation formula uses the wrong density for PLA.

// Cost estimate for PLA
volume_mm3 = 8500;
density    = 1.05;   // g/cm³ — WRONG material
spool_cost = 20;
spool_g    = 1000;

mass = (volume_mm3 / 1000) * density;
cost = mass * (spool_cost / spool_g);
echo("Est. cost: $", cost);

Q2. The safety checklist incorrectly marks ABS as safe to print in an open classroom without a fume enclosure.

Pre-print safety check:
[x] Filament loaded: ABS
[x] Ventilation: window open
[x] Ready to print in open classroom

Q3. The thermal runaway note is wrong — this protection must be enabled, not optional.

Printer setup checklist:
[ ] Bed level confirmed
[ ] Nozzle clean
[ ] Thermal runaway: optional, enable if desired

Q4. The post-print removal instruction is dangerous — it says to remove the part immediately at full temperature.

Post-print steps:
1. Print finishes.
2. Immediately remove part from heated bed with bare hands.
3. Store filament in a bag.

Q5. The filament density table has PLA and ABS swapped. Correct the table.

Material  | Density (g/cm³)
----------|----------------
PLA       | 1.05
ABS       | 1.24
PETG      | 1.27
TPU       | 1.20

Comment the Code (Questions 6–10)

Q6. Add comments explaining each line of this pre-print safety checklist script.

echo "=== Pre-Print Safety Check ===" > safety_log.txt
echo "Date: $(date)" >> safety_log.txt
echo "Filament: PLA" >> safety_log.txt
echo "Ventilation confirmed: YES" >> safety_log.txt
echo "Fire extinguisher present: YES" >> safety_log.txt
echo "Thermal runaway enabled: YES" >> safety_log.txt
echo "First layer watch timer: 15 min" >> safety_log.txt

Q7. Add comments to this cost-estimation snippet explaining each formula step.

volume_mm3    = 8500;
density_pla   = 1.24;
spool_price   = 20;
spool_weight  = 1000;

mass = (volume_mm3 / 1000) * density_pla;
cost = mass * (spool_price / spool_weight);

echo("Volume (mm³):", volume_mm3);
echo("Mass (g):", mass);
echo("Est. cost ($):", cost);

Q8. Add comments explaining each row of this filament selection table embedded in OpenSCAD comments.

// FILAMENT REFERENCE
// PLA   — density 1.24 g/cm³ — easiest, classroom default
// PETG  — density 1.27 g/cm³ — tougher, mild heat, moderate stringing
// ABS   — density 1.05 g/cm³ — high heat, fumes — enclosure required
// TPU   — density 1.20 g/cm³ — flexible, direct-drive extruder only
material = "PLA";

Q9. Add comments to this filament-selection module.

function filament_density(material) =
  (material == "PLA")  ? 1.24 :
  (material == "PETG") ? 1.27 :
  (material == "ABS")  ? 1.05 :
  (material == "TPU")  ? 1.20 :
  undef;

volume   = 6000;
mat      = "PLA";
density  = filament_density(mat);
mass     = (volume / 1000) * density;
echo("Material:", mat, "| Mass:", mass, "g");

Q10. Add comments explaining each step of this first-layer monitoring checklist embedded in an automation log.

echo "=== First Layer Monitor ===" >> print_log.txt
echo "Layer 1: bed adhesion — check in 2 min" >> print_log.txt
echo "Layer 2: no lifting at corners" >> print_log.txt
echo "Layer 3: temperature stable" >> print_log.txt
echo "Layer 3: no grinding sounds" >> print_log.txt
echo "First layer check complete — continue monitoring every 15 min" >> print_log.txt

3dMake — Lesson 6: Practical 3dm Commands and Text Embossing

Fix the Code (Questions 1–5)

Q1. The embossed text is positioned below the top face of the base plate instead of on top of it.

base_h = 5;
cube([80, 15, base_h]);
translate([40, 7.5, 0])
  linear_extrude(height=1.5)
    text("FRONT", size=6, font="Liberation Sans:style=Bold",
         halign="center", valign="center");

Q2. The debossed text cut is not deep enough — the extrude height doesn’t reach past the top face.

difference() {
  cube([80, 15, 5]);
  translate([40, 7.5, 4.5])
    linear_extrude(height=0.4)
      text("BACK", size=6, font="Liberation Sans:style=Bold",
           halign="center", valign="center");
}

Q3. The font is hardcoded in three separate places instead of using the single-constant pattern. Refactor it.

cube([80, 15, 5]);
translate([40, 7.5, 5])
  linear_extrude(height=1.5)
    text("FRONT", size=6, font="Liberation Sans:style=Bold",
         halign="center", valign="center");

translate([0, 20, 0]) cube([80, 15, 5]);
translate([40, 27.5, 10])
  linear_extrude(height=1.5)
    text("BACK", size=6, font="Liberation Sans:style=Bold",
         halign="center", valign="center");

Q4. The 3dm slice command is run before 3dm build, meaning it will slice the previous (stale) STL file.

3dm slice
3dm build
3dm info

Q5. The let() block uses wrong assignment syntax inside the expression.

module label_plate(msg, w=80, d=15, h=5) {
  let(text_size == h * 0.6) {
    cube([w, d, h]);
    translate([w/2, d/2, h])
      linear_extrude(height=1.5)
        text(msg, size=text_size, halign="center", valign="center");
  }
}

Comment the Code (Questions 6–10)

Q6. Add comments explaining every parameter of the text() function call.

linear_extrude(height=1.5)
  text(
    text      = "3dMake",
    size      = 10,
    font      = "Liberation Sans",
    halign    = "center",
    valign    = "baseline",
    spacing   = 1.0,
    direction = "ltr",
    language  = "en",
    script    = "latin"
  );

Q7. Add comments explaining each step of this embossed-plate module.

LABEL_FONT = "Liberation Sans:style=Bold";

module embossed_plate(message, w=80, d=15, h=5, text_size=8, relief=1.5) {
  cube([w, d, h]);
  translate([w/2, d/2, h])
    linear_extrude(height=relief)
      text(message, font=LABEL_FONT, size=text_size,
           halign="center", valign="center");
}

embossed_plate("FRONT");
translate([0, 20, 0]) embossed_plate("BACK");

Q8. Add comments explaining each command in the full 3dm suite.

3dm build
3dm build --clean
3dm build --watch
3dm info
3dm info --view front
3dm info --view top,front,isometric
3dm preview
3dm orient
3dm slice

Q9. Add comments to this debossed text implementation.

difference() {
  cube([80, 15, 5]);
  translate([40, 7.5, 5 - 0.8])
    linear_extrude(height=1.0)
      text("BACK", size=6, font="Liberation Sans:style=Bold",
           halign="center", valign="center");
}

Q10. Add comments to this variant-generation automation script.

#!/bin/bash
LABELS=("FRONT" "BACK" "LEFT" "RIGHT" "TOP" "BOTTOM")
mkdir -p build/labels

for LABEL in "${LABELS[@]}"; do
    OUT="build/labels/plate_${LABEL}.stl"
    openscad -D "label=\"${LABEL}\"" -o "$OUT" src/label_plate.scad
    echo "Built: $OUT"
done
echo "All label variants built."

3dMake — Lesson 7: Parametric Transforms and the Phone Stand

Fix the Code (Questions 1–5)

Q1. The transform order is wrong — the cube will orbit the origin instead of rotating in place.

rotate([0, 0, 45]) translate([20, 0, 0]) cube(5);

(Hint: to rotate in place then move, which should come first in reading order?)

Q2. The atan function is used instead of atan2, which will give wrong results in some quadrants.

dx = -5;
dy = 5;
angle = atan(dy / dx);
echo("Angle:", angle);

Q3. The minkowski() call uses $fn=64 on the secondary sphere during development, making renders extremely slow.

module rounded_box(w, d, h, r=3) {
  minkowski() {
    cube([w - 2*r, d - 2*r, h - r]);
    sphere(r=r, $fn=64);
  }
}
rounded_box(40, 30, 20);

Q4. The mirror() call uses the wrong axis vector — it reflects across the XZ plane instead of the YZ plane.

module ear_peg() {
  translate([20, 0, 0]) cylinder(r=4, h=8, $fn=32);
}
ear_peg();
mirror([0, 1, 0]) ear_peg();

Q5. The $preview variable is used backwards — the slow high-quality render runs during preview and the fast version runs during final build.

$fn = $preview ? 64 : 16;
sphere(r=20);

Comment the Code (Questions 6–10)

Q6. Add comments explaining the transform order rule demonstrated in these two examples.

translate([10, 0, 0]) rotate([0, 0, 45]) cube(5);

rotate([0, 0, 45]) translate([10, 0, 0]) cube(5);

Q7. Add comments explaining each trig function used in this circular placement loop.

for (i = [0:5]) {
  angle = i * 60;
  translate([cos(angle) * 25, sin(angle) * 25, 0])
    cylinder(r=3, h=5, $fn=16);
}

Q8. Add comments explaining each module and parameter in the phone stand assembly.

phone_w = 75;
phone_d = 9;
angle   = 65;

lip_h      = 15;
base_h     = 5;
cradle_wall= 3;
r_fillet   = 3;
base_d     = (phone_d + 10) / cos(90 - angle);

module base_plate() {
  flat_rounded_cube(phone_w + 20, base_d + 10, base_h, r_fillet);
}

module back_support() {
  rotate([angle - 90, 0, 0])
    flat_rounded_cube(phone_w + 6, cradle_wall, 60, r_fillet);
}

module lip() {
  rotate([angle - 90, 0, 0])
    translate([0, -lip_h, 0])
      flat_rounded_cube(phone_w + 6, lip_h + cradle_wall, cradle_wall, r_fillet);
}

base_plate();
translate([0, 0, base_h]) { back_support(); lip(); }

Q9. Add comments explaining how $preview enables fast development.

$fn = $preview ? 16 : 64;

module flat_rounded_cube(w, d, h, r=3) {
  if ($preview) {
    color("orange", 0.6) cube([w, d, h]);
  } else {
    minkowski() {
      cube([w - 2*r, d - 2*r, h]);
      cylinder(r=r, h=0.01, $fn=24);
    }
  }
}

flat_rounded_cube(40, 30, 20, r=4);

Q10. Add comments to this mirror() symmetry example.

module mounting_clip() {
  difference() {
    cube([15, 8, 10]);
    translate([7.5, -0.001, 2])
      cylinder(r=3, h=8.002, $fn=32);
  }
}

translate([0, 20, 0]) {
  mounting_clip();
  translate([15, 0, 0]) mirror([1, 0, 0]) mounting_clip();
}

3dMake — Lesson 8: Advanced Parametric Design and Interlocking Features

Fix the Code (Questions 1–5)

Q1. The tolerance constants are hardcoded inline instead of defined as named constants at the top. Refactor to use constants.

module peg(nominal=10, h=8) {
  cylinder(d=nominal - 0.3, h=h, $fn=32);
}
module socket(nominal=10, plate_t=3) {
  difference() {
    cylinder(d=nominal + 8, h=plate_t, $fn=32);
    translate([0, 0, -0.001])
      cylinder(d=nominal, h=plate_t + 0.002, $fn=32);
  }
}

Q2. The snap-fit beam parameters are specified for PLA but the comment says PETG. Fix the comment to match the geometry (do not change the numbers — assume PLA values are correct).

// PETG snap arm — thicker beam for stiffer material
module snap_arm_pla(beam_l=18, beam_t=1.8, beam_w=8) {
  cube([beam_w, beam_l, beam_t]);
  translate([0, beam_l, 0])
    cube([beam_w, 3, 2.5]);
}

Q3. The stacking-bin lip is positioned at the wrong Z height — it should start at bin_h, not bin_h - lip_h.

bin_h  = 40;
lip_h  = 5;
bin_w  = 80;
bin_d  = 60;
lip_clear = 0.25;

module stacking_lip() {
  translate([lip_clear, lip_clear, bin_h - lip_h])
    cube([bin_w - 2*lip_clear, bin_d - 2*lip_clear, lip_h]);
}

Q4. The M3 insert pocket extends above the host material (depth is too large for a 10mm plate).

difference() {
  cube([40, 30, 10]);
  translate([10, 15, -0.001]) cylinder(r=2.35, h=20, $fn=16);
  translate([30, 15, -0.001]) cylinder(r=2.35, h=20, $fn=16);
}

Q5. The dovetail female profile is given a negative clearance, which would make the slot smaller than the male part.

clearance = -0.2;

module dovetail_female(w_top=8, w_bot=12, h=5, c=clearance) {
  profile = [
    [-(w_bot/2 + c), -0.001], [ w_bot/2 + c, -0.001],
    [ w_top/2 + c,   h + c ], [-(w_top/2 + c), h + c]
  ];
  rotate([90, 0, 0])
    linear_extrude(50)
      polygon(profile);
}

Comment the Code (Questions 6–10)

Q6. Add comments explaining each tolerance constant and how it was determined.

PRESS_FIT_C = 0.2;
SLIP_FIT_C  = 0.3;
LOOSE_FIT_C = 0.45;
SNAP_C      = PRESS_FIT_C;

Q7. Add comments explaining each step of the tolerance test coupon.

nominal     = 10;
test_h      = 8;
plate_t     = 3;
socket_d_out= nominal + 8;
clearances  = [0.0, 0.1, 0.2, 0.3, 0.4];

module test_peg(clearance) {
  color("SteelBlue")
    cylinder(d=nominal - clearance, h=test_h, $fn=32);
}

module test_socket() {
  color("Coral")
  difference() {
    cylinder(d=socket_d_out, h=plate_t, $fn=32);
    translate([0, 0, -0.001])
      cylinder(d=nominal, h=plate_t + 0.002, $fn=32);
  }
}

Q8. Add comments explaining the physics behind each snap-arm parameter.

module snap_arm(beam_l=18, beam_t=1.8, beam_w=8, hook_h=1.5) {
  cube([beam_w, beam_l, beam_t]);
  translate([0, beam_l, 0])
    cube([beam_w, 3, hook_h + beam_t]);
}

Q9. Add comments to this dovetail joint module explaining the geometry.

module dovetail_male(l=50, w_top=8, w_bot=12, h=5) {
  profile = [
    [-w_bot/2, 0], [ w_bot/2, 0],
    [ w_top/2, h], [-w_top/2, h]
  ];
  rotate([90, 0, 0])
    linear_extrude(l)
      polygon(profile);
}

Q10. Add comments to this chamfered-box module explaining the geometry operation.

module chamfered_box(w, d, h, c=2) {
  difference() {
    cube([w, d, h]);
    translate([0, 0, h - c])
      difference() {
        cube([w, d, c + 0.001]);
        translate([c, c, 0])
          cube([w - 2*c, d - 2*c, c + 0.001]);
      }
  }
}
chamfered_box(50, 40, 20, c=3);

3dMake — Lesson 9: Automation and 3dm Workflows

Fix the Code (Questions 1–5)

Q1. The bash script is missing all three safety flags. Add them in the correct location.

#!/bin/bash
LOG="build/build.log"
mkdir -p build
openscad -o build/main.stl src/main.scad 2>&1 | tee -a "$LOG"
echo "Done"

Q2. The string parameter quoting is wrong — OpenSCAD will receive the label without inner double quotes.

LABEL="FRONT PANEL"
openscad -D "label=$LABEL" -o out.stl src/main.scad

Q3. The PowerShell script checks $LASTEXITCODE but doesn’t actually stop on failure.

$output = & openscad -o build\main.stl src\main.scad 2>&1
$output | Write-Host
if ($LASTEXITCODE -ne 0) { Write-Host "Build failed" }
Write-Host "Continuing..."

Q4. The batch script counter increment uses wrong CMD syntax.

@echo off
set SUCCESS=0
set FAIL=0
for %%W in (60 80 100) do (
    openscad -D "width=%%W" -o build\out_%%W.stl src\main.scad
    if %errorlevel% equ 0 (
        set SUCCESS = %SUCCESS% + 1
    ) else (
        set FAIL = %FAIL% + 1
    )
)
echo %SUCCESS% succeeded, %FAIL% failed

Q5. The file-size check uses the wrong comparison operator — it warns when the file is large instead of when it’s suspiciously small.

STL_SIZE=$(stat -c%s "build/main.stl")
if [ "$STL_SIZE" -gt 1000 ]; then
  echo "WARNING: STL suspiciously small"
fi

Comment the Code (Questions 6–10)

Q6. Add comments to every significant line of this robust bash build script.

#!/bin/bash
set -e
set -u
set -o pipefail

LOG_DIR="build/logs"
LOG_FILE="$LOG_DIR/build_$(date +%Y%m%d_%H%M%S).log"
mkdir -p "$LOG_DIR" build

log() {
  local level="$1"; shift
  echo "[$(date +%H:%M:%S)] [$level] $*" | tee -a "$LOG_FILE"
}

on_error() { log "ERROR" "Failed at line $1"; exit 1; }
trap 'on_error $LINENO' ERR

log "INFO" "=== Build started ==="
openscad -o build/main.stl src/main.scad 2>&1 | tee -a "$LOG_FILE"
STL_SIZE=$(stat -c%s "build/main.stl")
[ "$STL_SIZE" -gt 1000 ] || log "WARN" "STL small: ${STL_SIZE} bytes"
log "INFO" "Build OK: ${STL_SIZE} bytes"
3dm info 2>&1 | tee -a "$LOG_FILE"

Q7. Add comments explaining each string-quoting technique.

LABEL="FRONT PANEL"

openscad -D 'label="FRONT"' -o out1.stl src/main.scad
openscad -D "label=\"${LABEL}\"" -o out2.stl src/main.scad
echo "openscad -D 'label=\"${LABEL}\"' -o out3.stl src/main.scad"

Q8. Add comments to this PowerShell batch-build script.

$outputDir = "build\variants"
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null

$widths = @(60, 80, 100, 120)
$walls  = @(1.2, 1.6, 2.0)
$ok = 0; $fail = 0

foreach ($w in $widths) {
    foreach ($wt in $walls) {
        $name = "bracket_w${w}_wall${wt}"
        $out  = "$outputDir\${name}.stl"
        & openscad -D "width=$w" -D "wall=$wt" -o $out src\main.scad 2>$null
        if ($LASTEXITCODE -eq 0) { $ok++ } else { $fail++ }
    }
}
Write-Host "Done: $ok succeeded, $fail failed"

Q9. Add comments to this CI/CD GitHub Actions workflow.

name: Build STL Artifacts
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install OpenSCAD
        run: sudo apt-get install -y openscad
      - name: Install 3dm
        run: curl -fsSL https://get.3dmake.dev | bash
      - name: Build
        run: 3dm build
      - name: Verify
        run: 3dm info
      - name: Upload STL
        uses: actions/upload-artifact@v3
        with:
          name: stl-output
          path: build/*.stl

Q10. Add comments to this watch-mode automation script.

#!/bin/bash
set -e
SRC="src/main.scad"
LAST_MOD=""

echo "Watching: $SRC"
while true; do
    CURRENT_MOD=$(stat -c %Y "$SRC" 2>/dev/null || echo "0")
    if [ "$CURRENT_MOD" != "$LAST_MOD" ]; then
        LAST_MOD="$CURRENT_MOD"
        echo "[$(date +%H:%M:%S)] Change detected — rebuilding..."
        3dm build && 3dm info || echo "Build failed"
    fi
    sleep 2
done

3dMake — Lesson 10: Advanced Techniques — hull(), projection(), Non-Manifold Geometry

Fix the Code (Questions 1–5)

Q1. The hull() rounded box uses corner spheres, but they are placed at the wrong positions — at (0,0) instead of offset by the radius.

r = 5;
w = 40; d = 30; h = 20;

hull() {
  for (x = [0, w]) {
    for (y = [0, d]) {
      translate([x, y, 0]) sphere(r=r, $fn=24);
      translate([x, y, h]) sphere(r=r, $fn=24);
    }
  }
}

Q2. The minkowski() call uses $fn=64 on the secondary sphere during development instead of using $preview.

module rounded_box(w, d, h, r=4) {
  minkowski() {
    cube([w - 2*r, d - 2*r, h - r]);
    sphere(r=r, $fn=64);
  }
}
rounded_box(50, 40, 20, r=5);

Q3. The projection() cross-section is taken at the wrong height — the model is not shifted to put the cut plane at the intended Z level.

module phone_stand_example() {
  cube([90, 70, 5]);
  translate([15, 20, 5]) cylinder(r=5, h=35, $fn=24);
}

linear_extrude(1)
  projection(cut=true)
    phone_stand_example();

(The cut should be at z=10 of the model, not z=0.)

Q4. The non-manifold geometry fix is wrong — the zero-thickness wall is left in place.

// WRONG: zero-thickness internal wall (non-manifold)
difference() {
  cube([20, 20, 20]);
  translate([10, 0, 0]) cube([0, 20, 20]);  // zero-width slice — non-manifold
}

// ATTEMPTED FIX (still wrong):
difference() {
  cube([20, 20, 20]);
  translate([10, 0, 0]) cube([0, 20, 20]);  // still zero width
}

(Provide a correct fix using a non-zero wall thickness.)

Q5. The surface() call uses an incorrect file path that will silently produce no geometry.

scale([1, 1, 0.1])
  surface(file="heightmap/terrain.png", center=true, invert=false);

(The file path issue: if the file doesn’t exist, OpenSCAD produces empty geometry with no error. Write the correct verification approach using 3dm info output.)


Comment the Code (Questions 6–10)

Q6. Add comments explaining what hull() produces in each example.

hull() {
  cylinder(r=20, h=1, $fn=6);
  translate([0, 0, 30])
    sphere(r=8, $fn=32);
}

translate([60, 0, 0])
hull() {
  cylinder(r=6, h=2, $fn=32);
  translate([40, 0, 0])
    cylinder(r=1, h=2, $fn=16);
}

Q7. Add comments to this $preview-guarded minkowski() module.

module rounded_box(w, d, h, r=4) {
  if ($preview) {
    color("orange", 0.6) cube([w, d, h]);
  } else {
    minkowski() {
      cube([w - 2*r, d - 2*r, h - r]);
      sphere(r=r, $fn=12);
    }
  }
}

rounded_box(50, 40, 20, r=5);

Q8. Add comments explaining each projection() mode.

module phone_stand_example() {
  cube([90, 70, 5]);
  translate([15, 20, 5]) cylinder(r=5, h=35, $fn=24);
}

phone_stand_example();

color("LightGreen")
translate([110, 0, 0])
  linear_extrude(1)
    projection(cut=false)
      phone_stand_example();

color("LightCoral")
translate([220, 0, 0])
  linear_extrude(1)
    projection(cut=true)
      translate([0, 0, -3])
        phone_stand_example();

Q9. Add comments to this non-manifold geometry fix.

// PROBLEM: co-planar faces
difference() {
  cube([20, 20, 10]);
  translate([5, 5, 0])
    cube([10, 10, 10]);
}

// FIX: 0.001 offset rule applied
difference() {
  cube([20, 20, 10]);
  translate([5, 5, -0.001])
    cube([10, 10, 10.002]);
}

Q10. Add comments to this data-driven design using search() and lookup().

SIZES = [
  ["small",  20, 15, 8],
  ["medium", 35, 25, 12],
  ["large",  50, 40, 18]
];

function get_size(name, col) =
  SIZES[search([name], SIZES, 1, 0)[0]][col];

variant = "medium";
w = get_size(variant, 1);
d = get_size(variant, 2);
h = get_size(variant, 3);
cube([w, d, h]);
echo("Building:", variant, w, "x", d, "x", h);

3dMake — Lesson 11: Stakeholder-Centric Design and the Final Project

Fix the Code (Questions 1–5)

Q1. The requirement mapping uses a non-descriptive variable name — rename the variable so it traces directly to the functional requirement.

// FR1: Must fit standard bracelet diameters (50–70 mm)
x = 70;
inner_r = x / 2;
cylinder(r=inner_r + 2, h=10, $fn=64);

Q2. The acceptance criterion test is based on AI description instead of a measurable, deterministic check. Rewrite it.

Feature: bead hole diameter
Acceptance Test: run 3dm info and confirm description mentions "small hole"
Result: PASS

Q3. The bead module is missing an assert() for the cord-hole diameter — small holes will fail to print cleanly. Add the appropriate assertion.

module bead_A(size=15, detail=32) {
  difference() {
    sphere(r=size/2, $fn=detail);
    cylinder(r=1.0, h=size + 1, center=true, $fn=16);
  }
}

Q4. The Technical Design Specification variable is named x instead of a name that reflects its requirement origin.

// FR2: Base must be stable — width >= 1.2 × total height
total_height = 80;
x = 1.2 * total_height;
cube([x, x, 5]);

Q5. The iteration step changes a dimension by guessing without measuring first. Rewrite the comment to enforce the engineering approach.

// Iteration: user said "it's too tight"
// Changed slip_clearance from 0.25 to 0.35 — seems about right
slip_clearance = 0.35;

Comment the Code (Questions 6–10)

Q6. Add comments to this requirement-mapped parameter block.

// FR1
bracelet_max_d = 70;

// FR2
total_height = 80;
base_w = 1.2 * total_height;

// FR3
module tactile_marker() {
  sphere(r=2, $fn=16);
}

// FR4
SLIP_C = 0.3;

Q7. Add comments explaining each function in this final project’s modular structure.

module bead_A(size=15, detail=32, hole_r=1.0) {
  assert(size > 0, "size must be positive");
  assert(hole_r > 0 && hole_r < size/2, "hole_r out of range");
  difference() {
    sphere(r=size/2, $fn=detail);
    cylinder(r=hole_r, h=size + 1, center=true, $fn=16);
  }
}

module bead_B(size=12, detail=6, hole_r=1.0) {
  assert(size > 0, "size must be positive");
  difference() {
    cylinder(r=size/2, h=size, center=true, $fn=detail);
    cylinder(r=hole_r, h=size + 1, center=true, $fn=16);
  }
}

Q8. Add comments to this structured feedback log.

echo "=== Stakeholder Feedback — Iteration 1 ===" > feedback.txt
echo "Date: $(date)" >> feedback.txt
echo "Observation: user hesitated to locate clasp" >> feedback.txt
echo "Quote: 'the clasp blends in with the rest'" >> feedback.txt
echo "Measurement: clasp width = 8.2mm (designed 9.0mm)" >> feedback.txt
echo "Action: increase clasp_w by 0.8mm; reprint test coupon first" >> feedback.txt

Q9. Add comments to this user story and acceptance-criteria block embedded in the SCAD file.

// USER STORY
// As a jewelry collector,
// I want the holder to have 2mm clearance
// so that my bracelets slide on easily but don't fall off.

SLIP_C = 0.3;  // measured from test coupon

bracelet_max_d = 70;
holder_inner_r = (bracelet_max_d / 2) + SLIP_C;
holder_outer_r = holder_inner_r + 3;
holder_h = 10;

difference() {
  cylinder(r=holder_outer_r, h=holder_h, $fn=64);
  translate([0, 0, -0.001])
    cylinder(r=holder_inner_r, h=holder_h + 0.002, $fn=64);
}

Q10. Add comments to this complete design-thinking workflow script.

#!/bin/bash
PROJECT="$1"
BASE="$HOME/Documents/3d_projects/$PROJECT"

mkdir -p "$BASE"
cd "$BASE"
3dm new

cat > design_notes.md << EOF
# $PROJECT Design Notes
## Stakeholder Interview
## Functional Requirements
## Acceptance Criteria
## Technical Design Specification
## Iteration Log
EOF

echo "Project scaffolded: $BASE"
ls -1

Command Line Appendices — Complete Reference

Supplemental automation references for integrating OpenSCAD and 3dMake workflows with the three command-line environments covered in this curriculum. Each appendix is self-contained and maps directly to the corresponding CLI foundation curriculum.


Contents

AppendixShellTitle
Appendix ACMD / BatchCommand Line (CMD/Batch) Integration for SCAD Workflows
Appendix BPowerShellPowerShell Integration for SCAD Workflows
Appendix CGit Bash / POSIXGit Bash / POSIX Shell Integration for SCAD Workflows

All three appendices cover the same workflow stages — single-file build, batch directory build, parametric sweeps, logging, USB transfer, and network printer monitoring — using the idioms and tools native to each shell.



Appendix A: Command Line (CMD/Batch) Integration for SCAD Workflows


This appendix shows how traditional command-line (Windows CMD / batch) scripting automates SCAD workflows without requiring PowerShell. It mirrors the patterns in Appendix D but provides examples and idioms for cmd / batch files and systems that prefer native Windows command prompt scripts.

Overview: Why Automate with CMD/Batch?

  • Minimal dependencies: works on basic Windows installations.
  • Easy to call from other tools and CI systems that expect .bat helpers.
  • Useful for environments where PowerShell policy restrictions exist.

Prerequisites & Setup

Required Software

where openscad      :: OpenSCAD (path in PATH or full path required)
where prusa-slicer  :: PrusaSlicer (or your slicer)
where python        :: Python (optional)

Directory Structure (Windows style)

C:\Projects\3dMake\
+------ src\
+------ stl\
+------ gcode\
+------ logs\
+------ scripts\
       +------ build.bat
       +------ batch_build.bat

Notes on CMD vs PowerShell

  • CMD/batch has more limited error handling and no structured objects; rely on return codes and file checks.
  • Use full executable paths to avoid PATH surprises.

Basic Workflow: Single-file build (batch)

Create build.bat (simple example):

@echo off
rem build.bat - Convert SCAD -> STL -> G-code (minimal)
setlocal enabledelayedexpansion
set PROJECTROOT=%~dp0\..\
set SCADFILE=%1
if "%SCADFILE%"=="" (
  echo Usage: build.bat file.scad
  exit /b 1
)
set SCADPATH=%PROJECTROOT%src\%SCADFILE%
set STLPATH=%PROJECTROOT%stl\%~n1.stl
set GCODEPATH=%PROJECTROOT%gcode\%~n1.gcode

rem Export STL using OpenSCAD
"C:\Program Files\OpenSCAD\openscad.exe" -o "%STLPATH%" "%SCADPATH%"
if not exist "%STLPATH%" (
  echo ERROR: STL not created
  exit /b 1
)

rem Slice (example) - adjust path to slicer
"C:\Program Files\Prusa3D\PrusaSlicer\prusa-slicer.exe" --load-config-file "%~dp0\default.ini" -o "%GCODEPATH%" "%STLPATH%"
if not exist "%GCODEPATH%" (
  echo ERROR: G-code not created
  exit /b 1
)

echo BUILD COMPLETE: %GCODEPATH%
endlocal

Batch (directory) build

batch_build.bat can iterate files and call build.bat:

@echo off
set PROJECTROOT=%~dp0\..\
for /r "%PROJECTROOT%src" %%f in (*.scad) do (
  echo Processing %%~nxf
  call "%~dp0build.bat" "%%~nxf"
)

Parametric Sweeps (simple templating)

Because batch is limited for text templating, a common pattern is to use small helper scripts with sed/python or write a minimal templating helper in a language such as Python. Example invocation in batch:

rem Example: call a Python script to generate variants, then build
python "%~dp0/generate_variants.py" "%PROJECTROOT%src\bracelet_holder.scad"
call "%~dp0/batch_build.bat"

Logging and CSV output

Batch scripts can append simple CSV lines using echo redirection:

echo %DATE% %TIME%,%~n1,Success >> "%PROJECTROOT%logs\build_history.csv"

Send to Printer (USB copy)

rem Copy gcode to removable drive (E: example)
copy "%GCODEPATH%" E:\

Monitoring (networked printer) - using curl or PowerShell helper

curl on Windows or a small PowerShell one-liner may be used to query APIs. For pure CMD, ship a small helper .exe (curl) or call powershell -Command "Invoke-RestMethod ...".

Best Practices

  • Use full paths for all tools.
  • Check return codes (if errorlevel 1) after each step.
  • Keep batch scripts small; delegate complex text processing to Python/PowerShell.
  • Log to simple CSVs for human and machine parsing.


Appendix B: PowerShell Integration for SCAD Workflows


This appendix shows how PowerShell (command-line scripting) streamlines 3D design workflows, automating the repetitive tasks from design through printing. It bridges PowerShell_Foundation concepts with 3dMake_Foundation practical applications.

Referenced in: Lessons 9 (Automation), 10 (Mastery), and any lesson requiring batch operations

Prerequisites: Completion of PowerShell_Foundation (Lessons 1-6)

Overview: Why Automate SCAD Workflows?

Manual Workflow (Time-Consuming)

  1. Open SCAD manually -> Edit parameters -> Save -> Export STL
  2. Open Slicer manually -> Load STL -> Adjust settings -> Slice -> Export G-code
  3. Transfer G-code to printer via USB
  4. Record results in notebook
  5. Repeat for next variation (variant 2, variant 3, etc.)

Time: ~20-30 minutes per design iteration

Automated Workflow (Fast & Reproducible)

  1. Create PowerShell script with design parameters
  2. Script automatically:
    • Generates SCAD code
    • Exports to STL
    • Slices to G-code
    • Transfers to printer
    • Logs results
  3. Run script once, walk away
  4. Check results later

Time: 2-3 minutes per iteration (plus print time)

Benefits of Automation

  • [YES] Speed: 10x faster for batch operations
  • [YES] Consistency: No manual errors
  • [YES] Reproducibility: Same settings every time
  • [YES] Scalability: Test 5, 10, or 100 variations easily
  • [YES] Logging: Automatic documentation
  • [YES] Accessibility: Screen reader captures script output (not UI clicks)

Prerequisites & Setup

Required Software

# Check what you have installed
where openscad      # OpenSCAD
where prusa-slicer  # PrusaSlicer (or your slicer)
where python3       # Python (optional, for advanced scripts)

Directory Structure

Create a project directory:

C:\Projects\3dMake\
+------ src/
|   +------ bracelet_holder.scad
|   +------ phone_stand.scad
|   +------ stackable_bins.scad
+------ stl/
|   +------ bracelet_holder.stl
|   +------ phone_stand.stl
|   +------ stackable_bins.stl
+------ gcode/
|   +------ bracelet_holder.gcode
|   +------ phone_stand.gcode
|   +------ stackable_bins.gcode
+------ logs/
|   +------ batch_2024-01-15.log
|   +------ print_history.csv
+------ scripts/
    +------ build.ps1      (main build script)
    +------ batch_test.ps1 (test variations)
    +------ monitor.ps1    (monitor printer)

PowerShell Execution Policy

# Check current policy
Get-ExecutionPolicy
# If it's "Restricted", change it (requires admin)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Verify change
Get-ExecutionPolicy

Basic Workflow Automation

Script 1: Single-File Build

This script takes a SCAD file and converts it through the entire workflow:

# build.ps1 - Convert SCAD -> STL -> G-code
param(
    [string]$ScadFile,          # Input: bracelet_holder.scad
    [string]$OutputDir = ".\",  # Output directory
    [string]$SlicerConfig = "default"
)
# Set up paths
$ProjectRoot = "C:\Projects\3dMake"
$ScadFile = Join-Path $ProjectRoot "src" $ScadFile
$StlFile = Join-Path $ProjectRoot "stl" ([System.IO.Path]::GetFileNameWithoutExtension($ScadFile) + ".stl")
$GcodeFile = Join-Path $ProjectRoot "gcode" ([System.IO.Path]::GetFileNameWithoutExtension($ScadFile) + ".gcode")
$LogFile = Join-Path $ProjectRoot "logs" "build_$(Get-Date -Format 'yyyy-MM-dd').log"
# Log function
function Write-Log {
    param([string]$Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] $Message"
    Write-Host $logEntry
    Add-Content -Path $LogFile -Value $logEntry
}
Write-Log "Starting build for $($ScadFile | Split-Path -Leaf)"
# Step 1: Export STL
Write-Log "Step 1: Exporting SCAD to STL..."
$startTime = Get-Date
& "C:\Program Files\OpenSCAD\openscad.exe" `
    -o "$StlFile" `
    "$ScadFile"
$duration = (Get-Date) - $startTime
Write-Log " STL exported in $($duration.TotalSeconds) seconds: $StlFile"
# Verify STL exists
if (-not (Test-Path $StlFile)) {
    Write-Log "[NO] ERROR: STL file not created"
    exit 1
}
# Step 2: Slice to G-code
Write-Log "Step 2: Slicing STL to G-code..."
$startTime = Get-Date
& "C:\Program Files\Prusa3D\PrusaSlicer\prusa-slicer.exe" `
    --load-config-file "$SlicerConfig" `
    --export-gcode "$GcodeFile" `
    "$StlFile"
$duration = (Get-Date) - $startTime
Write-Log " G-code generated in $($duration.TotalSeconds) seconds: $GcodeFile"
# Verify G-code exists
if (-not (Test-Path $GcodeFile)) {
    Write-Log "[NO] ERROR: G-code file not created"
    exit 1
}
# Step 3: Get file info
$stlSize = (Get-Item $StlFile).Length / 1MB
$gcodeSize = (Get-Item $GcodeFile).Length / 1MB
Write-Log "File sizes: STL=$([math]::Round($stlSize, 2))MB, G-code=$([math]::Round($gcodeSize, 2))MB"
Write-Log " BUILD COMPLETE"
Write-Log "Ready to print: $GcodeFile"

Usage:

# Run the script
.\build.ps1 -ScadFile "bracelet_holder.scad"
# Output example:
# [2024-01-15 14:30:22] Starting build for bracelet_holder.scad
# [2024-01-15 14:30:23] Step 1: Exporting SCAD to STL...
# [2024-01-15 14:30:25]  STL exported in 2.41 seconds: ...
# [2024-01-15 14:30:26] Step 2: Slicing STL to G-code...
# [2024-01-15 14:30:28]  G-code generated in 2.31 seconds: ...
# [2024-01-15 14:30:28]  BUILD COMPLETE

Script 2: Batch Build (Multiple Files)

# batch_build.ps1 - Build all SCAD files in a directory
param(
    [string]$SourceDir = "C:\Projects\3dMake\src",
    [string]$SlicerConfig = "default"
)
$ProjectRoot = Split-Path $SourceDir
$buildScript = Join-Path $ProjectRoot "scripts" "build.ps1"
# Find all SCAD files
$scadFiles = Get-ChildItem -Path $SourceDir -Filter "*.scad" -Recurse
Write-Host "Found $($scadFiles.Count) SCAD files"
if ($scadFiles.Count -eq 0) {
    Write-Host "No SCAD files found in $SourceDir"
    exit 1
}
# Process each file
$results = @()
foreach ($file in $scadFiles) {
    Write-Host "`n--- Processing: $($file.Name) ---"
    $startTime = Get-Date
    # Run build script for this file
    & $buildScript -ScadFile $file.Name -SlicerConfig $SlicerConfig
    $duration = (Get-Date) - $startTime
    $results += [PSCustomObject]@{
        FileName = $file.Name
        DurationSeconds = $duration.TotalSeconds
        Status = "Success"
        Timestamp = Get-Date
    }
}
# Summary report
Write-Host "`n=== BATCH BUILD SUMMARY ==="
Write-Host "Files processed: $($results.Count)"
Write-Host "Total time: $([math]::Round(($results | Measure-Object -Property DurationSeconds -Sum).Sum, 1)) seconds"
# Save results to CSV
$csvPath = Join-Path $ProjectRoot "logs" "batch_$(Get-Date -Format 'yyyy-MM-dd-HHmmss').csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation
Write-Host "Results saved: $csvPath"

Usage:

.\batch_build.ps1 -SourceDir "C:\Projects\3dMake\src"
# Processes all .scad files automatically

Parametric Design Variation Testing

The Problem: Testing Multiple Parameter Values

You want to test the same design with different parameters (e.g., peg diameter: 5mm, 6mm, 7mm):

Manually:

  1. Open bracelet_holder.scad
  2. Change peg_diameter = 5
  3. Save, export, slice, print
  4. Change peg_diameter = 6
  5. Save, export, slice, print
  6. Change peg_diameter = 7
  7. Save, export, slice, print Time: 30 minutes

Automated Solution: Parametric Sweep

# parametric_sweep.ps1 - Test multiple parameter values
param(
    [string]$TemplateScad = "C:\Projects\3dMake\src\bracelet_holder.scad",
    [hashtable]$ParameterRanges = @{
        "peg_diameter" = @(5, 5.5, 6, 6.5, 7)
        "holder_width" = @(120, 127, 135)
    }
)
$ProjectRoot = "C:\Projects\3dMake"
$variantsDir = Join-Path $ProjectRoot "variants"
$buildScript = Join-Path $ProjectRoot "scripts" "build.ps1"
$logFile = Join-Path $ProjectRoot "logs" "parametric_sweep_$(Get-Date -Format 'yyyy-MM-dd-HHmmss').csv"
# Create variants directory
New-Item -ItemType Directory -Path $variantsDir -Force | Out-Null
# Read template
$template = Get-Content $TemplateScad -Raw
# Generate variants
$results = @()
$variantNum = 0
# For each diameter value
foreach ($dia in $ParameterRanges["peg_diameter"]) {
    # For each width value
    foreach ($width in $ParameterRanges["holder_width"]) {
        $variantNum++
        $variantName = "variant_dia${dia}_width${width}"
        $variantScad = Join-Path $variantsDir "$variantName.scad"
        # Create variant SCAD file with parameters
        $content = $template `
            -replace 'peg_diameter = [\d.]+', "peg_diameter = $dia" `
            -replace 'holder_width = [\d.]+', "holder_width = $width"
        $content | Set-Content $variantScad
        Write-Host "Generated: $variantName"
        # Build variant (STL + G-code)
        $startTime = Get-Date
        # Export to STL
        & "C:\Program Files\OpenSCAD\openscad.exe" `
            -o (Join-Path $ProjectRoot "stl" "$variantName.stl") `
            $variantScad
        $duration = (Get-Date) - $startTime
        # Record result
        $results += [PSCustomObject]@{
            Variant = $variantName
            PegDiameter = $dia
            HolderWidth = $width
            BuildTimeSeconds = $duration.TotalSeconds
            Status = "Success"
            Timestamp = Get-Date
        }
        Write-Host "   Built in $($duration.TotalSeconds) seconds"
    }
}
# Save results
$results | Export-Csv -Path $logFile -NoTypeInformation
Write-Host "`nParametric sweep complete: $($results.Count) variants generated"
Write-Host "Results: $logFile"
# Summary statistics
Write-Host "`n=== PARAMETER RANGES TESTED ==="
Write-Host "Peg diameters: $($ParameterRanges['peg_diameter'] -join ', ')"
Write-Host "Holder widths: $($ParameterRanges['holder_width'] -join ', ')"
Write-Host "Total combinations: $($results.Count)"

Usage:

$ranges = @{
    "peg_diameter" = @(5, 5.5, 6, 6.5, 7)
    "holder_width" = @(120, 127, 135)
}
.\parametric_sweep.ps1 -TemplateScad "bracelet_holder.scad" -ParameterRanges $ranges
# Generates 15 variants automatically (5 x 3)

Output CSV:

Variant,PegDiameter,HolderWidth,BuildTimeSeconds,Status,Timestamp
variant_dia5_width120,5,120,2.4,Success,2024-01-15 14:35:22
variant_dia5_width127,5,127,2.5,Success,2024-01-15 14:35:25
variant_dia5_width135,5,135,2.3,Success,2024-01-15 14:35:28
...

Automated Print Documentation

Script: Print Logging & Quality Tracking

# log_print.ps1 - Document each print with metadata
param(
    [string]$GcodeFile,
    [string]$ProjectName,
    [string]$Material = "PLA",
    [string]$Notes = ""
)
$ProjectRoot = "C:\Projects\3dMake"
$printLogCsv = Join-Path $ProjectRoot "logs" "print_history.csv"
# Get G-code file info
$gcodeInfo = Get-Item $GcodeFile
$gcodeSize = $gcodeInfo.Length / 1MB
$estimatedTime = EstimateTime $GcodeFile  # See function below
# Calculate estimated cost
$weightG = EstimateWeight $GcodeFile
$materialCostPerKg = 20  # PLA at $20/kg
$estimatedCost = ($weightG / 1000) * $materialCostPerKg
# Create log entry
$entry = [PSCustomObject]@{
    PrintID = "PRINT_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
    ProjectName = $ProjectName
    Date = Get-Date
    Material = $Material
    GcodeFile = $gcodeFile
    GcodeSizeMB = [math]::Round($gcodeSize, 2)
    EstimatedTimeHours = [math]::Round($estimatedTime / 3600, 2)
    EstimatedWeightG = [math]::Round($weightG, 1)
    EstimatedCostUSD = [math]::Round($estimatedCost, 2)
    Notes = $Notes
}
# Append to CSV
if (Test-Path $printLogCsv) {
    $entry | Export-Csv -Path $printLogCsv -NoTypeInformation -Append
} else {
    $entry | Export-Csv -Path $printLogCsv -NoTypeInformation
}
Write-Host "Print logged:"
Write-Host "  Project: $ProjectName"
Write-Host "  File: $($gcodeInfo.Name)"
Write-Host "  Estimated time: $([math]::Round($estimatedTime / 3600, 2)) hours"
Write-Host "  Estimated weight: $([math]::Round($weightG, 1))g"
Write-Host "  Estimated cost: $$([math]::Round($estimatedCost, 2))"
# Function to estimate print time from G-code (simplified)
function EstimateTime {
    param([string]$GcodeFile)
    $lines = @(Get-Content $GcodeFile | Select-String "^G1" | Measure-Object).Count
    # Rough estimate: 10 lines per second
    return $lines / 10
}
# Function to estimate weight from G-code (simplified)
function EstimateWeight {
    param([string]$GcodeFile)
    # G-code filament estimate (if supported by your slicer)
    $content = Get-Content $GcodeFile -Raw
    if ($content -match "filament used = ([\d.]+)") {
        return [double]$matches[1]
    } else {
        return 0  # Fallback
    }
}

Usage:

.\log_print.ps1 `
    -GcodeFile "C:\Projects\3dMake\gcode\bracelet_holder.gcode" `
    -ProjectName "Bracelet Holder" `
    -Material "PLA" `
    -Notes "Final design, tested with actual bracelets"

Printer Communication & Monitoring

Script: Send G-code to Printer (USB)

# send_to_printer.ps1 - Copy G-code to printer USB
param(
    [string]$GcodeFile,
    [string]$PrinterUSBLetter = "E"  # E:, F:, G:, etc.
)
$printerDrive = "${PrinterUSBLetter}:\"
# Check if USB drive connected
if (-not (Test-Path $printerDrive)) {
    Write-Host "[NO] ERROR: Printer USB not found at $PrinterUSBLetter"
    Write-Host "Available drives:"
    Get-PSDrive -PSProvider FileSystem | Where-Object Name -Like "[D-Z]" | Select-Object Name
    exit 1
}
# Copy file
$filename = Split-Path $GcodeFile -Leaf
$destination = Join-Path $printerDrive $filename
Copy-Item -Path $GcodeFile -Destination $destination -Force
Write-Host " G-code copied to printer USB:"
Write-Host "  From: $GcodeFile"
Write-Host "  To: $destination"
Write-Host "`nNext steps:"
Write-Host "  1. Eject USB safely from computer"
Write-Host "  2. Insert USB into printer"
Write-Host "  3. Select file on printer screen"
Write-Host "  4. Press print"

Usage:

.\send_to_printer.ps1 -GcodeFile "C:\Projects\3dMake\gcode\bracelet_holder.gcode" -PrinterUSBLetter "E"

Script: Monitor Printer Status (Network Printers)

# monitor_printer.ps1 - Check printer status via API
param(
    [string]$PrinterIP,
    [int]$CheckInterval = 30,    # seconds
    [int]$MaxChecks = 240        # 2 hours max
)
$printerUrl = "[https://example.com](https://example.com)
$checksPerformed = 0
Write-Host "Monitoring printer at $PrinterIP"
Write-Host "Check interval: $CheckInterval seconds"
Write-Host "Ctrl+C to stop`n"
while ($checksPerformed -lt $MaxChecks) {
    try {
        # Get printer status
        $response = Invoke-WebRequest -Uri $printerUrl -UseBasicParsing -ErrorAction Stop
        $status = $response.Content | ConvertFrom-Json
        $state = $status.state.text
        $progress = $status.progress.completion
        $timeRemaining = $status.progress.printTimeLeft
        Write-Host "[$((Get-Date).ToString("HH:mm:ss"))] State: $state | Progress: $progress% | Time remaining: $timeRemaining seconds"
        # If print completed, exit loop
        if ($state -eq "Operational") {
            Write-Host "`n Print complete!"
            break
        }
    } catch {
        Write-Host "Connection error: $_"
    }
    Start-Sleep -Seconds $CheckInterval
    $checksPerformed++
}
if ($checksPerformed -ge $MaxChecks) {
    Write-Host "Max monitoring time reached. Stopping."
}

Usage:

.\monitor_printer.ps1 -PrinterIP "192.168.1.100" -CheckInterval 30

Complete Workflow Integration

Master Script: Design -> Print -> Log

# full_workflow.ps1 - Complete automation from design to printing
param(
    [string]$ProjectName,
    [string]$ScadFile,
    [string]$Material = "PLA",
    [string]$Notes = "",
    [switch]$SendToPrinter,
    [string]$PrinterUSBLetter = "E"
)
$ProjectRoot = "C:\Projects\3dMake"
Write-Host "=== 3dMake Full Workflow Automation ==="
Write-Host "Project: $ProjectName"
Write-Host ""
# Step 1: Build (SCAD -> STL -> G-code)
Write-Host "Step 1: Building..."
& "$ProjectRoot\scripts\build.ps1" -ScadFile $ScadFile
if ($LASTEXITCODE -ne 0) { exit 1 }
# Step 2: Log the print
Write-Host "`nStep 2: Logging print metadata..."
$gcodeFile = Join-Path $ProjectRoot "gcode" ([System.IO.Path]::GetFileNameWithoutExtension($ScadFile) + ".gcode")
& "$ProjectRoot\scripts\log_print.ps1" `
    -GcodeFile $gcodeFile `
    -ProjectName $ProjectName `
    -Material $Material `
    -Notes $Notes
# Step 3: Send to printer (optional)
if ($SendToPrinter) {
    Write-Host "`nStep 3: Sending to printer..."
    & "$ProjectRoot\scripts\send_to_printer.ps1" `
        -GcodeFile $gcodeFile `
        -PrinterUSBLetter $PrinterUSBLetter
}
Write-Host "`n Workflow complete!"

Usage:

# Full workflow with automatic printer transfer
.\full_workflow.ps1 `
    -ProjectName "Bracelet Holder" `
    -ScadFile "bracelet_holder.scad" `
    -Material "PLA" `
    -Notes "Final design, v2 with improved peg strength" `
    -SendToPrinter `
    -PrinterUSBLetter "E"

PowerShell Skills Applied to SCAD

Lesson Mapping: PowerShell -> SCAD Workflows

PowerShell LessonSCAD ApplicationExample
PS 1: NavigationWorking with project directoriesUsing cd to navigate src/ -> stl/ -> gcode/
PS 2: File ManipulationCopying, organizing SCAD filesCopy design files, organize variants by date
PS 3: Piping & ObjectsPass data between scripts$results | Export-Csv exports analysis
PS 4: Variables & AliasesParameterize SCAD workflowsVariables store file paths, material types, etc.
PS 5: Functions & ModulesReusable automation blocksBuild, slice, log = functions in one script
PS Unit TestVerify workflow correctnessTest that STL file exists before slicing

Example: File Navigation with SCAD Projects

# Navigate between SCAD project folders
$ProjectRoot = "C:\Projects\3dMake"
# Go to source directory
cd "$ProjectRoot\src"
Get-ChildItem -Filter "*.scad"  # List all SCAD files
# Process each file
foreach ($file in Get-ChildItem -Filter "*.scad") {
    Write-Host "Processing: $($file.Name)"
    # Do something with each file
}
# Go to output directory and check results
cd "$ProjectRoot\stl"
Get-ChildItem -Filter "*.stl" | Measure-Object -Sum

Example: Working with Piping & Objects

# Build all files, then get statistics
Get-ChildItem -Path "$ProjectRoot\src" -Filter "*.scad" |
    ForEach-Object {
        # Build each one
        & .\build.ps1 -ScadFile $_.Name
    } |
    # Analyze results
    Group-Object -Property Status |
    Select-Object Name, Count

Accessibility Considerations

Why PowerShell for SCAD?

  1. Screen Reader Friendly: Console output = text (not UI clicks)
  2. Scriptable: Can run overnight, results logged
  3. Auditable: Every step written to log file
  4. Shareable: Scripts document the process for others
  5. Testable: Can verify each step independently

Example: Accessible Build Output

[2024-01-15 14:30:22] Starting build for bracelet_holder.scad
[2024-01-15 14:30:23] Step 1: Exporting SCAD to STL...
[2024-01-15 14:30:25]  STL exported in 2.41 seconds
[2024-01-15 14:30:26] Step 2: Slicing STL to G-code...
[2024-01-15 14:30:28]  G-code generated in 2.31 seconds
[2024-01-15 14:30:28] File sizes: STL=2.15MB, G-code=4.32MB
[2024-01-15 14:30:28]  BUILD COMPLETE

Ready to print: C:\Projects\3dMake\gcode\bracelet_holder.gcode

All information is text-based and sequential-perfectly accessible to screen readers.

Best Practices & Tips

1. Always Log Everything

function Write-Log {
    param(
        [string]$Message,
        [string]$LogFile
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $entry = "[$timestamp] $Message"
    Write-Host $entry
    Add-Content -Path $LogFile -Value $entry
}

2. Verify Steps Succeed Before Continuing

# Don't just run commands-check they worked
& "C:\Program Files\OpenSCAD\openscad.exe" -o "$StlFile" "$ScadFile"
if (-not (Test-Path $StlFile)) {
    Write-Log "ERROR: STL creation failed"
    exit 1
}
Write-Log " STL created successfully"

3. Make Scripts Reusable

# BAD: Hardcoded paths
$scadFile = "C:\Users\John\Desktop\bracelet_holder.scad"
# GOOD: Parameters with defaults
param(
    [string]$ScadFile = "bracelet_holder.scad",
    [string]$ProjectRoot = "C:\Projects\3dMake"
)
$fullPath = Join-Path $ProjectRoot "src" $ScadFile

4. Use Configuration Files

# config.ps1 - Centralized settings
$Config = @{
    ProjectRoot = "C:\Projects\3dMake"
    OpenSCADPath = "C:\Program Files\OpenSCAD\openscad.exe"
    SlicerPath = "C:\Program Files\Prusa3D\PrusaSlicer\prusa-slicer.exe"
    PrinterUSB = "E"
    DefaultMaterial = "PLA"
    DefaultInfill = 20
}
# Use in scripts:
# . .\config.ps1
# & $Config.OpenSCADPath ...

Troubleshooting Automated Workflows

ProblemCauseSolution
Scripts won’t runExecution policySet-ExecutionPolicy -ExecutionPolicy RemoteSigned
Command not foundTool not in PATHSpecify full path: & "C:\Program Files\OpenSCAD\openscad.exe"
Files not createdWrong working directoryUse absolute paths with Join-Path
Script hangsWaiting for user inputDisable UI input; use -o flag for batch operations
CSV data corruptedSpecial characters in notesProperly quote strings in CSV export
No output/loggingPath doesn’t existCreate directory first: New-Item -Type Directory -Path ... -Force

Summary: PowerShell + SCAD Integration Benefits

Time Savings

TaskManualAutomatedSavings
Single design build5 min2.5 min50%
Test 10 parameter variations50 min5 min90%
Batch processing 20 designs100 min10 min90%

Consistency

  • [YES] Same process every time (no missed steps)
  • [YES] Reproducible results (exact same settings)
  • [YES] Comprehensive logging (documentation automatic)

Scalability

  • [YES] 1 design or 1,000 designs = same time commitment
  • [YES] Run overnight for batch operations
  • [YES] Easy to expand with new features

Accessibility

  • [YES] All interaction is text-based (screen reader friendly)
  • [YES] Results logged in CSV (machine-readable, sortable)
  • [YES] Repeatable (can verify steps later)

Next Steps

  1. Try the basic build script (Script 1) with one of your SCAD files
  2. Add logging (Script 3) to track what you create
  3. Test parametric sweeps (Script 2) with design variations
  4. Integrate full workflow (Script 5) for complete automation
  5. Customize config.ps1 for your specific setup

Remember: Start simple, test each script individually, then combine them into larger workflows. PowerShell is most powerful when built incrementally!


Appendix C: Git Bash / POSIX Shell Integration for SCAD Workflows


This appendix mirrors Appendix D (PowerShell) but provides examples for Git Bash (mingw) or other POSIX-compatible shells on Windows, macOS, and Linux. Use these scripts when you prefer shell utilities (bash, sed, awk, curl) and Unix-like tooling.

Overview: Why Git Bash / POSIX Shell?

  • Leverage standard Unix tools for text processing and automation.
  • Cross-platform: same scripts often work on Linux/macOS and Windows via Git Bash.
  • Good fit for containerized CI like GitHub Actions.

Prerequisites & Setup

Required Software

command -v openscad   # OpenSCAD
command -v prusa-slicer # PrusaSlicer (or use CLI slicer)
command -v python3     # Python (optional)
command -v curl        # curl for API calls

Directory Structure (POSIX-style)

~/projects/3dMake/
|- src/
|- stl/
|- gcode/
|- logs/
`- scripts/
  |- build.sh
  `- batch_build.sh

Basic Workflow: Single-file build (bash)

scripts/build.sh:

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
SCAD_FILE="$1"
SCAD_PATH="$ROOT_DIR/src/$SCAD_FILE"
STL_PATH="$ROOT_DIR/stl/${SCAD_FILE%.*}.stl"
GCODE_PATH="$ROOT_DIR/gcode/${SCAD_FILE%.*}.gcode"

echo "Exporting SCAD -> STL: $SCAD_FILE"
"/c/Program Files/OpenSCAD/openscad.exe" -o "$STL_PATH" "$SCAD_PATH" || { echo "STL export failed"; exit 1; }

echo "Slicing STL -> G-code"
"/c/Program Files/Prusa3D/PrusaSlicer/prusa-slicer.exe" --load-config-file "$ROOT_DIR/scripts/default.ini" -o "$GCODE_PATH" "$STL_PATH" || { echo "Slicing failed"; exit 1; }

echo "BUILD COMPLETE: $GCODE_PATH"

Notes:

  • Paths to GUI apps on Windows may need the /c/Program\ Files/... form under Git Bash, or call the native .exe with full quoted path.
  • On Linux/macOS adjust executable paths accordingly.

Batch Build (directory)

scripts/batch_build.sh:

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
find "$ROOT_DIR/src" -name "*.scad" -print0 | while IFS= read -r -d '' file; do
  fname="$(basename "$file")"
  echo "Building $fname"
  "$ROOT_DIR/scripts/build.sh" "$fname"
done

Parametric Sweeps

Use sed or python to template parameter changes, then call build.sh for each variant. Example (bash + python hybrid):

python3 scripts/gen_variants.py "$ROOT_DIR/src/bracelet_holder.scad" --out variants/
for v in variants/*.scad; do
  ./scripts/build.sh "$(basename "$v")"
done

Logging & CSV

Append simple CSV lines using printf:

printf "%s,%s,Success\n" "$(date +'%Y-%m-%d %H:%M:%S')" "${SCAD_FILE%.*}" >> "$ROOT_DIR/logs/build_history.csv"

Send to Printer (USB)

# Copy to mounted USB drive (example mount point /media/usb)
cp "$GCODE_PATH" "/media/usb/"

Monitoring (network printers)

Use curl to call a printer API (e.g., OctoPrint):

curl -s "[https://example.com](https://example.com) -H "X-Api-Key: $API_KEY" | jq .

Best Practices

  • Use set -euo pipefail for safer scripts.
  • Use mktemp or a variants/ directory for generated files.
  • Keep heavy text processing to python if logic becomes complex.
  • Make scripts executable (chmod +x scripts/*.sh).

3dMake and OpenSCAD Appendices — Complete Reference

Comprehensive reference materials for the 3dMake Foundation and OpenSCAD curriculum, including makerspace locators, tool references, slicing guides, material science, quality assurance procedures, and advanced design concepts.


Contents

AppendixTitle
Makerspace Index: UtahUtah Makerspace Index (By County)
Makerspace Index: United StatesNational Makerspace Guide — State-by-State Index
Appendix A3DMake CLI Cheat Sheet
Appendix BComprehensive Slicing Guide — All Major Slicers
Appendix CMaterial Properties and Selection Guide
Appendix DTolerance Testing and Quality Assurance Matrix
Appendix EAdvanced OpenSCAD Concepts


Makerspace Index: Utah (By County)


Beaver County

(No makerspace info discovered.)

Box Elder County

(No makerspace info discovered.)

Cache County

Logan Library – Cytiva STEM Makerspace

Bambu 3D printers, mini printers, vinyl cutter, sublimation printer, laser engraver, heat presses, craft cutters, and media digitization tools.1

Carbon County

Southeast Education Service Center (SESC)

STEM kits with coaching, curriculum, and project materials for regional schools.2

Iron County

Southern Utah University – Thunderworks Makerspace

Campus/community fabrication lab with CNC tools, 3D printers, and electronics benches.2

Salt Lake County

Salt Lake City Public Library – Creative Lab

3D printers, Cricut cutters, photography/film tools, Adobe Creative Cloud, recording booth.3

Salt Lake County Library – Create Spaces

3D printers, VR, robotics, A/V studios, DIY repair tools across six branches.4

Make Salt Lake

Community makerspace with woodshop, metal shop, laser cutters, electronics benches, and 3D printer lab.2

University of Utah – Marriott Library ProtoSpace

Prusa MK4/XL 3D printers, 3D scanning, prototyping tools.5

Washington County

Washington County Library – Sid Atkin Makerspace

3D printers, CNC cutter, sewing machines, woodworking tools, electronics kits, VR.6

Utah Tech University – Jr. Makerspace

K–12 and community maker training and fabrication tools.2

Weber County

Weber County Library Makerspaces

Laser cutters, vinyl cutters, laminators, embroidery machines, scanners, and design software stations.7


Endnotes


National Makerspace Guide (United States) — State-by-State Index


A comprehensive state‑by‑state index of ways to locate makerspaces, hackerspaces, Fab Labs, library labs, and community workshops across the U.S., including national directories and state‑level aggregators.

National Directories (Best Starting Points)

Nation of Makers – U.S. Maker Organization Map

Crowdsourced map of U.S.-based maker organizations including makerspaces, hackerspaces, DIY bio labs, Fab Labs, school labs, library spaces, and maker events.8

Makerspace.com – Global & U.S. Makerspace Directory

Large, continuously updated worldwide directory with city/state filters.9

Makerspacedir.com – Makerspace Directory

U.S.-focused listing of makerspaces, hackerspaces, Fab Labs, coworking/maker hybrids, and creative community spaces.10

POIData Makerspace Industry Report (2026)

Lists 1,046 makerspaces in the U.S., with counts by state (e.g., CA 84, FL 45, CO 37, OR 35). Useful for statistical and geographical reference.11

WorkMakeCreate – Public & Free-to-Use Makerspace Finder

Locates community workshops, tool libraries, and free/low‑cost makerspaces by ZIP code.12

GlobalSpec Makerspace Provider List

Allows filtering of makerspaces by U.S. state with business profiles and categories.13


State-by-State Makerspace Index (United States)

Below is a national omnibus index generated from directories that explicitly list makerspaces by state. States not listed did not appear in any verified directory results.

Alabama

  • 2 makerspaces listed on GlobalSpec.13

Arizona

  • Makerspaces listed on Makerspace Directory and GlobalSpec. Example: Coco‑Op (Flagstaff).14

California

  • 84 makerspaces (highest nationwide).11
  • Multiple listings in Makerspace.com, GlobalSpec, and WorkMakeCreate.

Colorado

  • 37 makerspaces statewide.11
  • Makerspaces include Denhac (Denver).13

Connecticut

  • 2 makerspaces listed on GlobalSpec (e.g., CT Hackerspace).13

District of Columbia

  • 3 makerspaces statewide.11
  • Example: HacDC.13

Florida

  • 45 makerspaces statewide.11
  • Example: Marion County Maker Collective.14

Georgia

  • 19 makerspaces statewide.11
  • Example: SparkMacon.14

Hawaii

  • 2 makerspaces listed on GlobalSpec.13

Idaho

  • 5 makerspaces statewide (from POIData).11

Illinois

  • 4 makerspaces listed on GlobalSpec (e.g., mHUB Chicago).13

Indiana

  • 3 makerspaces listed on GlobalSpec; 22 statewide per POIData.11

Iowa

  • 11 statewide makerspaces.11
  • Example: Cedar Valley Makers.13

Kansas

  • 14 statewide makerspaces.11

Kentucky

  • 6 statewide makerspaces.11

Louisiana

  • 3 statewide makerspaces.11

Maine

  • 11 statewide makerspaces.11

Maryland

  • 12 statewide makerspaces.11
  • Example: Baltimore Hackerspace.13

Massachusetts

  • 24 statewide makerspaces.11
  • Example: Framingham Makerspace.15

Michigan

  • 18 statewide makerspaces.11
  • Large concentration documented by Maker Works directory.16

Minnesota

  • 27 statewide makerspaces.11

Mississippi

  • 3 statewide makerspaces.11

Missouri

  • 16 statewide makerspaces.11
  • Example: Arch Reactor (St. Louis).13

Montana

  • 9 statewide makerspaces.11

Nebraska

  • 7 statewide makerspaces.11

Nevada

  • 6 statewide makerspaces.11

New Hampshire

  • 4 statewide makerspaces.11

New Jersey

  • 12 statewide makerspaces.11

New Mexico

  • 8 statewide makerspaces.11

New York

  • 28 statewide makerspaces.11
  • Dozens indexed by WorkMakeCreate (NYC region).12

North Carolina

  • 28 statewide makerspaces.11

North Dakota

  • (No verified listings in sources)

Ohio

  • 22 statewide makerspaces.11
  • Example: Akron-Summit Public Library makerspace.11

Oklahoma

  • 8 statewide makerspaces.11

Oregon

  • 35 statewide makerspaces.11

Pennsylvania

  • 15 statewide makerspaces.11

Rhode Island

  • 3 statewide makerspaces.11
  • Example: Tinker|Bristol.14

South Carolina

  • 15 statewide makerspaces.11

South Dakota

  • 2 statewide makerspaces.11

Tennessee

  • 16 statewide makerspaces; GlobalSpec lists 3 (e.g., CBI Maker Space).13

Texas

  • 33 statewide makerspaces (3rd highest).11
  • Example: 10BitWorks (San Antonio).9

Utah

  • 9 statewide makerspaces.11

Vermont

  • 6 statewide makerspaces.11

Virginia

  • 19 statewide makerspaces.11
  • Example: 757 Makerspace (Norfolk).9

Washington

  • 28 statewide makerspaces.11
  • Example: Confluent Space (Richland).13

West Virginia

  • 2 statewide makerspaces.11

Wisconsin

  • 17 statewide makerspaces.11

Wyoming

  • 6 statewide makerspaces.11

Endnotes


Appendix A: 3DMake CLI Cheat Sheet


A comprehensive reference for the 3dm command-line tool used alongside OpenSCAD for 3D printing.


Basic Syntax

3dm ACTIONS... [OPTIONS]... [INPUT_FILE]

You can combine multiple actions in a single command, and most single-letter options can be used with a single dash (e.g. -s 1.5 instead of --scale 1.5).


Quick Examples

3dm build                                    # Build the default model
3dm build orient slice                       # Build, auto-orient, then slice
3dm build orient slice -m cover -o supports  # With a specific model and overlay
3dm info alpaca.stl                          # Get info about an STL file
3dm preview alpaca.stl                       # Preview an STL file
3dm slice print alpaca.stl                   # Slice and send an STL to printer
3dm image --angle top --angle front          # Export rendered images

All Actions

Project Setup & Management

ActionDescription
setupSet up 3DMake for the first time, or overwrite/upgrade existing settings (printer profile, Gemini AI key, OctoPrint connection)
newInteractively create a new 3DMake project directory structure (src/, build/, 3dmake.toml, starter .scad file)
3dm setup       # First-time setup or re-configure
3dm new         # Create a new project (prompts for directory name)

Build Pipeline

These actions can be chained together in sequence:

ActionDescription
buildCompile the OpenSCAD .scad source file into a .stl model
orientAuto-orient the model to minimize the need for supports (uses Tweaker3)
sliceSlice the model into printer-ready G-code using PrusaSlicer
printSend the sliced G-code to the printer (OctoPrint, Bambu LAN, or Bambu Connect)
3dm build                        # Just compile OpenSCAD -> STL
3dm build orient                 # Compile then auto-orient
3dm build orient slice           # Compile, orient, then slice
3dm build orient slice print     # Full pipeline: compile -> orient -> slice -> print
3dm slice print                  # Slice an already-built model and print it
3dm print                        # Send an already-sliced file to the printer

Note: Actions automatically trigger their dependencies. For example, slice will imply build if needed.


Inspection & Visualization

ActionDescription
infoDisplay mesh dimensions and center point; optionally get an AI description of the model (requires Gemini or OpenRouter API key configured)
previewProduce a 2D silhouette projection of the model (outputs a flat STL for quick reference)
imageExport one or more rendered PNG images of the model from specified viewpoints
3dm info                         # Show mesh size/center info
3dm info --interactive           # Info + start AI chat session about the model
3dm info model.stl               # Info on a specific STL file
3dm preview                      # Generate 3-silhouette projection (default view)
3dm preview --view topsil        # Generate top-only silhouette
3dm image --angle top            # Render image from top viewpoint
3dm image --angle top --angle front --angle left  # Multiple viewpoints
3dm image --colorscheme slicer_dark --image-size 1920x1080

Available --view options for preview:

View NameDescription
3silThree-view silhouette (top, left, front) — default
topsilTop-down silhouette only
leftsilLeft-side silhouette only
rightsilRight-side silhouette only
frontsilFront silhouette only
backsilBack silhouette only

Available --colorscheme options for image:

Scheme NameDescription
slicer_lightOrange model on light gray background
slicer_darkOrange model on dark background
light_on_darkFloral white model on dark background

Available --angle options for image:
above_front_left, above_front_right, above_back_left, above_back_right, top, bottom


Configuration Editors

These are all isolated actions (cannot be combined with other actions):

ActionDescription
edit-modelOpen the current model’s .scad source file in your configured editor
edit-profileOpen the current printer profile .ini file in your editor
edit-overlayOpen (or create) a slicer settings overlay file in your editor
edit-profile-gcodeInteractively select and edit a G-code script embedded in the printer profile
edit-promptEdit the AI prompt used by the info command
edit-global-configEdit the global defaults.toml settings file (printer, API keys, etc.)
3dm edit-model                    # Edit the default model's .scad file
3dm edit-model -m lid             # Edit a specific model (lid.scad)
3dm edit-profile                  # Edit the current printer profile
3dm edit-profile -p prusa_mk4     # Edit a specific profile
3dm edit-overlay                  # Prompted to choose/create an overlay
3dm edit-overlay -o supports      # Edit the "supports" overlay directly
3dm edit-profile-gcode            # Choose and edit a G-code script in the profile
3dm edit-prompt                   # Edit the AI description prompt
3dm edit-global-config            # Edit global settings (defaults.toml)

Library Management

ActionDescription
list-librariesList all available OpenSCAD libraries in the catalog, showing which are installed and their versions
install-librariesDownload and install any libraries required by the current project (as specified in 3dmake.toml)
3dm list-libraries        # See available and installed libraries
3dm install-libraries     # Install missing project libraries

Listing Configuration

ActionDescription
list-profilesList all available printer profiles
list-overlaysList all available slicer setting overlays
3dm list-profiles         # See all printer profiles
3dm list-overlays         # See all overlays (with profile restrictions if any)

Diagnostics & Info

ActionDescription
test-connectTest the connection to the configured print server (OctoPrint or Bambu LAN)
helpDisplay the help message with all actions and options
versionPrint the 3DMake version, program location, and config directory
3dm test-connect          # Test printer connection
3dm help                  # Show help
3dm version               # Show version info

All Options

OptionShortTypeDescription
--scale-sfloat or autoScale the model by a decimal factor (e.g. 1.5 for 150%, 0.5 for 50%)
--model-mstringSelect a specific model by name in a multi-model project (omit .scad extension)
--profile-pstringSelect a printer profile by name
--overlay-ostringApply a slicer settings overlay; can be used multiple times
--view-vstringSelect the preview view type (see view options above)
--angle-astringSet a viewpoint for image export; can be used multiple times
--copies-cintNumber of copies to slice/print (default: 1)
--interactive-iflagStart an interactive AI chat after the info command
--colorschemestringColor scheme name for image export
--image-sizeWxHImage dimensions in pixels (e.g. 1920x1080, default: 1080x720)
--debugflagEnable debug output (shows full subprocess logs, raises exceptions)
--help / --h-hflagDisplay help and exit

Input Files

You can pass an .stl or .scad file directly instead of running inside a project directory:

3dm info model.stl                  # Inspect a standalone STL
3dm preview model.stl               # Preview a standalone STL
3dm slice print model.stl           # Slice and print a standalone STL
3dm build model.scad                # Build a standalone SCAD file -> STL
3dm image model.stl --angle top     # Render image from standalone STL

When passing a .scad file, build is automatically added to the action list.


Project File (3dmake.toml) & Global Config (defaults.toml)

Both files use identical TOML keys. defaults.toml lives in the config directory and sets machine-wide defaults. 3dmake.toml lives in your project root and overrides the global defaults for that project only.

Run 3dm edit-global-config to open defaults.toml in your editor.
Settings set via CLI flags (e.g. --scale, --profile) override both files at runtime.


General / Project Settings

KeyTypeDefaultDescription
model_namestring"main"The default model name. Maps to src/<name>.scad and build/<name>.stl
project_namestring(folder name)Project name used as a prefix on output filenames. Auto-detected from directory name if not set
scalefloat1.0Scale factor applied during slicing. 1.0 = 100%, 1.5 = 150%, 0.5 = 50%
copiesint1Number of copies to slice/print in one run
strict_warningsboolfalsePass --hardwarnings to OpenSCAD — treat all warnings as errors during build
min_3dmake_versionstring(none)Minimum required 3DMake version to run this project. Prevents running with outdated installs
interactiveboolfalseDefault to interactive AI chat mode after info
debugboolfalseEnable debug/verbose output globally
# General project settings
model_name = "main"
project_name = "my-widget"
scale = 1.0
copies = 1
strict_warnings = true
min_3dmake_version = "1.2.0"
interactive = false
debug = false

OpenSCAD / Build Settings

KeyTypeDefaultDescription
librarieslist of strings[]OpenSCAD libraries required by this project. Names must be lowercase and match entries in the library catalog. Install with 3dm install-libraries
local_librarieslist of strings[]Paths to local library directories (absolute or relative to project root) to add to OPENSCADPATH during build
# OpenSCAD library dependencies
libraries = ["openscad-threads", "bosl2"]

# Local/custom libraries not in the catalog
local_libraries = ["./lib/my-custom-parts", "/home/user/shared-scad-libs"]

Printer & Slicer Settings

KeyTypeDefaultDescription
printer_profilestring(required)Name of the printer profile .ini file to use (without the .ini extension). Set during 3dm setup
overlayslist of strings[]Default slicer setting overlays to apply on every slice. Profile-specific versions are preferred over default ones when available
viewstring"3sil"Default preview view type used by the preview action
image_angleslist of strings[]Default viewpoint angles for the image action
colorschemestring"slicer_light"Default color scheme for the image action
image_sizestring"1080x720"Default image export dimensions in WIDTHxHEIGHT pixels
# Slicer configuration
printer_profile = "prusa_mk4"
overlays = ["fast-draft"]

# Preview and image defaults
view = "3sil"
image_angles = ["above_front_left", "top"]
colorscheme = "slicer_light"
image_size = "1920x1080"

KeyTypeDefaultDescription
print_modestring(required to print)How to send prints to the printer. One of: "octoprint", "bambu_lan", "bambu_connect"
auto_start_printsbooltrueWhen using OctoPrint, automatically start the print after uploading the file
# Print sending mode
print_mode = "octoprint"       # Options: "octoprint", "bambu_lan", "bambu_connect"
auto_start_prints = true

OctoPrint Connection

Used when print_mode = "octoprint". Test with 3dm test-connect.

KeyTypeDefaultDescription
octoprint_hoststring(none)Full URL to your OctoPrint server, including protocol (e.g. "http://octopi.local" or "http://192.168.1.50")
octoprint_keystring(none)OctoPrint Application API key. Generate in OctoPrint > Settings > Application Keys
# OctoPrint connection (set in defaults.toml, not project toml)
octoprint_host = "http://octopi.local"
octoprint_key = "ABC123DEF456..."

Bambu Labs Connection

Used when print_mode = "bambu_lan". Test with 3dm test-connect.

KeyTypeDefaultDescription
bambu_hoststring(none)Local IP address of your Bambu printer on your network (e.g. "192.168.1.42")
bambu_serial_numberstring(none)Printer serial number (found in the printer’s settings screen or Bambu Studio)
bambu_access_codestring(none)Local network access code shown on the printer screen (Settings > WLAN)
# Bambu Labs LAN connection (set in defaults.toml, not project toml)
bambu_host = "192.168.1.42"
bambu_serial_number = "01S00C123456789"
bambu_access_code = "12345678"

AI Description Settings

Used by the info action. Set up during 3dm setup or via 3dm edit-global-config.

KeyTypeDefaultDescription
gemini_keystring(none)Google Gemini API key for AI model descriptions. Free tier allows ~50 requests/day. Get one at aistudio.google.com/app/apikey
openrouter_keystring(none)OpenRouter API key (alternative to Gemini for AI descriptions, supports many LLM providers)
llm_namestring(provider default)Specific LLM model name to use with Gemini or OpenRouter (e.g. "gemini-1.5-flash", "google/gemini-pro-vision")
# AI description keys (set in defaults.toml only — keep out of project toml!)
gemini_key = "AIzaSy..."
openrouter_key = "sk-or-..."
llm_name = "gemini-1.5-flash"

Editor Settings

KeyTypeDefaultDescription
editorstring(system default)Command used to open files for editing (e.g. "code", "vim", "notepad", "subl"). Used by all edit-* actions
edit_in_backgroundboolfalseLaunch the editor as a background process (non-blocking). Set to true on Windows where GUI editors are common
# Editor configuration (typically set in defaults.toml)
editor = "code"                 # VS Code
edit_in_background = true       # Don't block the terminal while editing

# Other common editor values:
# editor = "vim"
# editor = "nano"
# editor = "subl"               # Sublime Text
# editor = "notepad"            # Windows Notepad

Complete Annotated Example

A fully commented 3dmake.toml for a real project:

# ── Project identity ──────────────────────────────────────────────
model_name = "enclosure"           # src/enclosure.scad -> build/enclosure.stl
project_name = "pi-case"           # Output files named pi-case-enclosure.gcode etc.
min_3dmake_version = "1.2.0"       # Fail loudly if tool is out of date

# ── Build ─────────────────────────────────────────────────────────
strict_warnings = true             # Treat OpenSCAD warnings as errors
libraries = ["openscad-threads"]   # Needs thread library (run: 3dm install-libraries)
local_libraries = ["./lib"]        # Also include project-local ./lib/ directory

# ── Slicing ───────────────────────────────────────────────────────
printer_profile = "prusa_mk4"      # Use profiles/prusa_mk4.ini
scale = 1.0                        # No scaling
copies = 1
overlays = ["fast-draft"]          # Always slice with fast-draft settings

# ── Images & Preview ──────────────────────────────────────────────
view = "3sil"
image_angles = ["above_front_left", "top"]
colorscheme = "slicer_light"
image_size = "1920x1080"

# ── Printing ──────────────────────────────────────────────────────
# (Print connection settings like octoprint_host belong in defaults.toml,
#  not here, since they are machine-specific not project-specific)
print_mode = "octoprint"
auto_start_prints = true

A fully commented defaults.toml for a machine-wide config:

# ── Machine-wide defaults (in ~/.config/3dmake/defaults.toml) ────

# General defaults
model_name = "main"
view = "3sil"
auto_start_prints = true

# Editor
editor = "code"
edit_in_background = true          # For GUI editors that return immediately

# Printer
printer_profile = "prusa_mk4"

# OctoPrint connection
print_mode = "octoprint"
octoprint_host = "http://octopi.local"
octoprint_key = "ABC123DEF456GHI789..."

# AI descriptions (keep sensitive keys here, not in project toml)
gemini_key = "AIzaSyABC123..."
llm_name = "gemini-1.5-flash"

Typical Workflows

New Project from Scratch

3dm new                    # Create project structure
cd my-project
3dm edit-model             # Write your OpenSCAD model
3dm build                  # Verify it compiles
3dm info                   # Check dimensions
3dm build orient slice print  # Full pipeline

Iterate on an Existing Model

3dm edit-model             # Edit the .scad source
3dm build                  # Recompile
3dm preview                # Quick visual check
3dm slice -o supports      # Slice with supports overlay
3dm print                  # Send to printer

Working with a Standalone STL

3dm info my-model.stl
3dm preview my-model.stl
3dm image my-model.stl --angle above_front_left --angle top
3dm slice print my-model.stl

Export Images for Documentation

3dm image \
  --angle above_front_left \
  --angle above_front_right \
  --angle top \
  --colorscheme slicer_light \
  --image-size 1920x1080

Environment Variables

VariableDescription
3DMAKE_CONFIG_DIROverride the default configuration directory path

Configuration Directory Structure

~/.config/3dmake/         (or $3DMAKE_CONFIG_DIR)
├── defaults.toml          Global settings (printer, API keys, etc.)
├── profiles/
│   └── my_printer.ini     Printer profiles (slicer settings)
├── overlays/
│   ├── default/
│   │   └── supports.ini   Default overlays (apply to all printers)
│   └── my_printer/
│       └── supports.ini   Printer-specific overlay overrides
├── libraries/             Installed OpenSCAD libraries
└── templates/             Starter templates for new projects/overlays

Overlays

Overlays are partial PrusaSlicer .ini files that override specific slicer settings without replacing the entire printer profile. They are the primary way to switch between print quality modes, enable supports, adjust strength, or any other per-print tuning — without touching your base printer profile.

How Overlays Work

  1. When slicing, 3DMake loads your base printer profile first, then applies each overlay in order, with later overlays winning over earlier ones.
  2. Overlay files only need to contain the keys you want to change — all other profile settings are preserved.
  3. 3DMake looks for overlays in two places, preferring the printer-specific version if it exists:
    • overlays/<printer_profile>/<name>.ini ← preferred
    • overlays/default/<name>.ini ← fallback

Creating and Editing Overlays

3dm edit-overlay                  # Prompted to pick or create an overlay
3dm edit-overlay -o strong        # Open (or create) the "strong" overlay directly
3dm list-overlays                 # See all available overlays

When creating a new overlay via 3dm edit-overlay, you can optionally lock it to a specific printer profile. A locked overlay lives under overlays/<profile>/ and only applies when that profile is active.

Using Overlays

# Apply a single overlay
3dm slice -o strong

# Apply multiple overlays (stacked in order, last wins on conflicts)
3dm slice -o fine -o supports

# Set a default overlay for a project in 3dmake.toml
overlays = ["strong"]

# CLI overlay replaces (not adds to) the toml default
3dm slice -o draft              # Uses only "draft", ignores toml default

Overlay File Format

Overlay .ini files use the same key=value format as PrusaSlicer profiles. You only need to include the keys you want to override.

# overlays/default/strong.ini
# Keys and values are identical to PrusaSlicer's config export format.
# Lines starting with # are comments and are ignored.

perimeters = 4
top_solid_layers = 6
bottom_solid_layers = 6
fill_density = 40%
fill_pattern = grid

Key PrusaSlicer INI Settings Reference

The most useful keys for overlay tuning, with types and sample values:

Shell / Wall Strength

KeyDescriptionSample Values
perimetersNumber of outer wall loops2 (draft) · 3 (normal) · 5 (strong)
top_solid_layersSolid layers on the top surface3 (draft) · 5 (normal) · 8 (strong)
bottom_solid_layersSolid layers on the bottom surface3 (draft) · 4 (normal) · 6 (strong)
top_solid_min_thicknessMinimum top skin thickness in mm (overrides layer count if larger)0.5 · 0.8 · 1.0
bottom_solid_min_thicknessMinimum bottom skin thickness in mm0.5 · 0.8 · 1.0
external_perimeters_firstPrint outer walls before inner walls (better surface quality)0 · 1
thin_wallsDetect and print thin walls that would otherwise be missed0 · 1

Infill

KeyDescriptionSample Values
fill_densityInfill percentage5% · 15% · 20% · 40% · 60%
fill_patternInfill patterngrid · gyroid · honeycomb · cubic · rectilinear · lightning · triangles
top_fill_patternPattern for top solid layersrectilinear · monotonic · concentric · smooth
bottom_fill_patternPattern for bottom solid layersrectilinear · monotonic · concentric
infill_every_layersOnly infill every N layers (speeds up print, reduces strength)1 · 2 · 3
solid_infill_every_layersForce solid infill every N layers0 (off) · 5
infill_overlapHow much infill overlaps with perimeters (%)15% · 25%

Layer Height & Speed

KeyDescriptionSample Values
layer_heightStandard layer height in mm0.1 · 0.15 · 0.2 · 0.3
first_layer_heightHeight of the first layer (absolute mm or %)0.2 · 0.25 · 75%
perimeter_speedSpeed for perimeter walls (mm/s)40 · 60 · 80
external_perimeter_speedSpeed for outermost wall only (slower = better quality)25 · 35 · 50%
infill_speedSpeed for infill (mm/s)60 · 80 · 120
solid_infill_speedSpeed for solid infill layers (mm/s)50 · 70
top_solid_infill_speedSpeed for top surface layers (slower = smoother)30 · 40 · 50
travel_speedNon-extrusion travel speed (mm/s)130 · 180 · 250
first_layer_speedFirst layer speed (mm/s or %)20 · 30 · 50%

Supports

KeyDescriptionSample Values
support_materialEnable support structures0 · 1
support_material_autoAuto-detect where supports are needed0 · 1
support_material_thresholdOverhang angle above which supports are added (degrees)40 · 45 · 55
support_material_patternSupport infill patternrectilinear · honeycomb · lightning
support_material_spacingDistance between support lines (mm)2 · 2.5 · 3
support_material_contact_distanceZ gap between support and part (mm)0.1 · 0.2 · 0.25
support_material_interface_layersDense interface layers between support and part0 · 2 · 3

Cooling & Bridging

KeyDescriptionSample Values
coolingEnable fan cooling0 · 1
min_fan_speedMinimum fan speed %20 · 35 · 50
max_fan_speedMaximum fan speed %50 · 80 · 100
bridge_fan_speedFan speed during bridges %80 · 100
bridge_speedExtrusion speed for bridges (mm/s)20 · 30 · 40
bridge_flow_ratioFlow rate multiplier for bridges0.8 · 0.9 · 1.0

Skirt, Brim & Raft

KeyDescriptionSample Values
skirtsNumber of skirt loops0 · 1 · 3
skirt_distanceDistance from part to skirt (mm)3 · 5 · 6
brim_widthBrim width in mm (0 = disabled)0 · 3 · 5 · 8
raft_layersNumber of raft layers (0 = disabled)0 · 2 · 3

Temperature

KeyDescriptionSample Values
temperatureHotend temperature for all layers (°C)200 · 215 · 230
first_layer_temperatureHotend temperature for first layer only215 · 225 · 235
bed_temperatureBed temperature for all layers (°C)0 · 55 · 60 · 80
first_layer_bed_temperatureBed temperature for first layer only60 · 65 · 85

Sample Overlay: strong.ini

For functional parts, mechanical components, or anything that needs to survive stress. Heavier walls, more solid layers, higher infill, slower outer perimeters.

# overlays/default/strong.ini
# Heavy-duty print — maximizes strength at the cost of time and filament.

# Shell: thick walls and solid layers
perimeters = 5
top_solid_layers = 7
bottom_solid_layers = 6
top_solid_min_thickness = 1.2
bottom_solid_min_thickness = 1.0
external_perimeters_first = 1

# Infill: dense cubic for near-isotropic strength
fill_density = 50%
fill_pattern = cubic
infill_overlap = 25%

# Speed: slower outer wall for better layer adhesion
external_perimeter_speed = 25
perimeter_speed = 45
top_solid_infill_speed = 30

# First layer: slower for bed adhesion
first_layer_speed = 20

# Cooling: slightly reduced to improve layer bonding on perimeters
max_fan_speed = 70

Sample Overlay: draft.ini

For quick test fits, rough prototypes, or checking dimensions before committing to a full print. Faster speeds, minimal walls, low infill, thicker layers.

# overlays/default/draft.ini
# Fast draft print — sacrifices surface quality and strength for speed.

# Shell: minimum viable walls
perimeters = 2
top_solid_layers = 3
bottom_solid_layers = 3

# Infill: low density, fast pattern
fill_density = 10%
fill_pattern = grid

# Layer height: thick layers = fewer passes = faster print
# NOTE: layer_height must be <= 75% of nozzle diameter.
# For a 0.4mm nozzle, max is 0.3mm.
layer_height = 0.3

# Speed: push everything faster
perimeter_speed = 80
external_perimeter_speed = 60
infill_speed = 120
solid_infill_speed = 90
top_solid_infill_speed = 60
travel_speed = 200
first_layer_speed = 30

# Cooling: full fan to keep up with fast extrusion
min_fan_speed = 50
max_fan_speed = 100

Sample Overlay: fine.ini

For display models, miniatures, parts with fine surface detail, or anything where appearance matters more than speed. Thin layers, many perimeters, slow outer walls, smooth top surfaces.

# overlays/default/fine.ini
# Fine detail print — maximizes surface quality and dimensional accuracy.

# Shell: many perimeters for crisp edges and thick solid skins
perimeters = 4
top_solid_layers = 8
bottom_solid_layers = 5
top_solid_min_thickness = 1.0
external_perimeters_first = 1
thin_walls = 1

# Infill: moderate density with monotonic top for smooth finish
fill_density = 20%
fill_pattern = gyroid
top_fill_pattern = monotonic
bottom_fill_pattern = monotonic

# Layer height: thin layers for fine Z resolution
# NOTE: must be >= 25% of nozzle diameter to ensure reliable extrusion.
# For a 0.4mm nozzle, minimum is ~0.08mm; 0.1mm is safe.
layer_height = 0.1
first_layer_height = 0.2

# Speed: slow everything down for precision
perimeter_speed = 40
external_perimeter_speed = 20
infill_speed = 60
solid_infill_speed = 40
top_solid_infill_speed = 25
bridge_speed = 20
first_layer_speed = 15

# Cooling: strong cooling for clean overhangs and bridges
min_fan_speed = 50
max_fan_speed = 100
bridge_fan_speed = 100
bridge_flow_ratio = 0.85

# Brim: small brim helps adhesion for tall fine parts
brim_width = 3

Sample Overlay: supports.ini

Enable automatic support structures for models with steep overhangs. Stack with other quality overlays.

# overlays/default/supports.ini
# Enable automatic supports for overhangs > 45 degrees.

support_material = 1
support_material_auto = 1
support_material_threshold = 45
support_material_pattern = lightning
support_material_spacing = 2.5
support_material_contact_distance = 0.2
support_material_interface_layers = 2

Sample Overlay: no-supports.ini

Explicitly disable supports — useful when your base profile has them on by default.

# overlays/default/no-supports.ini
support_material = 0
support_material_auto = 0

Stacking Overlays

Overlays are applied left to right, so later overlays win on any conflicting keys. This lets you compose print settings modularly:

# Fine quality WITH supports
3dm slice -o fine -o supports

# Strong walls but fast draft speed (fine conflicts: perimeter_speed in draft wins)
3dm slice -o strong -o draft

# Strong structural settings + supports, no brim (add a tiny no-brim override)
3dm slice -o strong -o supports -o no-brim

You can also set permanent default overlays for a project in 3dmake.toml, while adding extra ones at the CLI:

# 3dmake.toml — always use strong as the base for this project
overlays = ["strong"]
# At CLI: strong (from toml) is REPLACED by the CLI overlay list
3dm slice -o strong -o supports   # Both applied
3dm slice -o fine                 # Only fine — replaces toml default entirely

Tip: Name your overlays by intent (strong, draft, fine, supports, vase-mode, no-brim) rather than by settings (40pct-infill). This keeps the CLI readable and lets you tune the overlay file without renaming references everywhere.


Action Dependency & Chain Rules

Implied Action Dependencies

Some actions automatically trigger prerequisite actions. You never need to spell these out manually — 3DMake inserts them for you.

print
  └── slice (implied)
        └── build (implied, if scad source exists)

image
  └── load-mesh (internal, implied)

info
  └── measure-mesh (internal, implied)
        └── load-mesh (internal, implied)

preview
  └── measure-mesh (internal, implied)
        └── load-mesh (internal, implied)

orient
  (no implied actions — operates on an already-built STL)

So running 3dm print on a project with OpenSCAD source will automatically run build -> slice -> print in order. You only need to be explicit when you want to stop partway through (e.g. 3dm build to just check compilation without slicing).

last_in_chain — Actions That Must Come Last

Three actions are marked last_in_chain, meaning no other pipeline actions can follow them in the same command. Attempting to do so is an error.

ActionWhy it’s last
imageProduces image files; nothing meaningful can follow a render
infoTerminal inspection command; no build artifact is produced
previewProduces a projection STL; slicing a silhouette is not useful
# ✅ Valid — last_in_chain actions used alone or at the end
3dm build image
3dm build orient image
3dm info
3dm build preview

# ❌ Invalid — actions after a last_in_chain action
3dm image slice        # ERROR: 'image' cannot be followed by 'slice'
3dm info build         # ERROR: 'info' cannot be followed by 'build'
3dm preview print      # ERROR: 'preview' cannot be followed by 'print'

Isolated Actions

A separate category called isolated means the action cannot be combined with any other action at all — it must be the only verb on the command line. All edit-* actions, setup, new, version, help, test-connect, list-profiles, list-overlays, list-libraries, and install-libraries are isolated.

# ✅ Valid
3dm edit-model
3dm setup
3dm list-profiles

# ❌ Invalid
3dm edit-model build    # ERROR: edit-model is isolated
3dm setup new           # ERROR: setup is isolated

Full Action Execution Order

When you request multiple actions, they always execute in this fixed internal order regardless of how you type them on the command line:

setup -> new -> build -> load-mesh* -> measure-mesh* -> info -> orient ->
image -> preview -> slice -> print -> list-profiles -> list-overlays ->
edit-model -> edit-overlay -> edit-profile -> edit-profile-gcode ->
edit-prompt -> edit-global-config -> list-libraries -> install-libraries ->
test-connect -> help -> version

_(Actions marked _ are internal and cannot be requested directly.)*

This means 3dm slice build and 3dm build slice are identical — order of verbs on the command line does not matter.


Multi-Model Projects

A single 3DMake project can contain multiple OpenSCAD models. Each model is a separate .scad file in the src/ directory.

Directory Layout

my-project/
├── 3dmake.toml
├── src/
│   ├── main.scad        ← default model (model_name = "main")
│   ├── lid.scad
│   ├── bracket.scad
│   └── insert.scad
└── build/               ← generated STLs and GCode land here
    ├── main.stl
    ├── lid.stl
    └── my-project-main.gcode

Selecting a Model

# Uses model_name from 3dmake.toml (default: "main")
3dm build slice

# Override at the CLI with --model / -m
3dm build slice -m lid
3dm build slice -m bracket
3dm info -m insert

# edit-model also respects -m
3dm edit-model -m lid

Setting a Per-Model Default in 3dmake.toml

# 3dmake.toml
model_name = "bracket"    # Everyone on this project defaults to the bracket model

Output File Naming

Output G-code files are named using the pattern:

<project_name>-<model_name>.gcode          # 1 copy
<project_name>-<model_name>-x3.gcode       # 3 copies (--copies 3)

For example, a project named pi-case building the lid model with 2 copies produces:

build/pi-case-lid-x2.gcode

If project_name is not set in 3dmake.toml, it is auto-detected from the directory name.

Tip: Shared Parameters Across Models

A common OpenSCAD pattern is a shared params.scad file included by all models:

src/
├── params.scad      ← shared dimensions, tolerances, material choices
├── main.scad        ← include <params.scad>
├── lid.scad         ← include <params.scad>
└── bracket.scad     ← include <params.scad>

This way changing one dimension in params.scad propagates to every model, and you can rebuild all variants with a shell loop:

for model in main lid bracket; do
    3dm build slice -m $model
done

Special INI Keys

3dm_bed_center

This is a 3DMake-specific key (not a standard PrusaSlicer key) that you can add to a printer profile or overlay. It works around a PrusaSlicer CLI bug where models are not correctly centered on non-rectangular or offset build volumes.

# In a printer profile .ini or overlay .ini
# Value is "X,Y" coordinates of the bed center in mm
3dm_bed_center = 117.5,117.5    # Prusa MK3/MK4 (235x235mm bed)
3dm_bed_center = 110,110        # 220x220mm bed
3dm_bed_center = 150,150        # 300x300mm bed
3dm_bed_center = 175,162.5      # Prusa XL (350x325mm bed)

When this key is present, 3DMake passes --center X,Y to the PrusaSlicer CLI automatically. You should set this in your printer profile rather than an overlay, since it is specific to the physical printer’s bed geometry.


AI Prompt Customization

The info action sends rendered images of your model to an AI (Gemini or OpenRouter) along with a text prompt. The default prompt asks for a general physical description of the object. You can customize this prompt to get more targeted or useful output.

Editing the Prompt

3dm edit-prompt    # Opens the prompt file in your configured editor

The prompt file lives at:

~/.config/3dmake/prompt.txt    (or $3DMAKE_CONFIG_DIR/prompt.txt)

If the file does not exist when you run 3dm edit-prompt, 3DMake creates it from a built-in default automatically.

What the Prompt Receives

The AI receives your prompt text plus six rendered PNG images of the model taken from these fixed viewpoints: above_front_left, above_front_right, above_back_left, above_back_right, top, and bottom. Each image is 768×768 pixels.

Sample Prompts

Default-style — general physical description:

You are analyzing a 3D model for 3D printing. Describe the object's physical
shape, identifying any notable geometric features, symmetry, overhangs, thin
walls, or small details that might affect printability. Be concise and factual.

Printability review — focused on print problems:

You are a 3D printing expert reviewing a model before printing. Examine these
views and identify:
1. Any overhangs greater than 45 degrees that will need supports
2. Thin walls or small features that may not print reliably at 0.4mm nozzle diameter
3. The best orientation for printing (which face should be on the bed)
4. Any other potential print quality issues

Be specific about locations (e.g. "the underside of the lip on the left side").

Dimensional estimation — for sanity-checking scale:

Based on the shape and proportions of this 3D model, estimate what real-world
object it most resembles and what its approximate dimensions might be in
millimeters. Note any features that suggest a specific scale (screw holes,
finger clearances, standard hardware interfaces, etc.).

Design feedback — for iterating on a model:

You are reviewing a 3D model for functional and aesthetic design quality.
Comment on: whether the design looks structurally sound, any places where
the geometry looks unintentional or messy, whether any features look like
they might be too fragile, and one specific improvement suggestion.

Interactive mode (3dm info --interactive) lets you follow up with specific questions after the initial AI response, such as asking it to focus on a particular feature or compare proportions.


Troubleshooting

Setup & Configuration

3DMake settings and print options have not been set up on this machine. Run 3dm setup before any other command. This creates the config directory, copies default profiles, and walks you through initial configuration.

Printer profile 'X' does not exist. Run 3dm list-profiles to see valid profile names. Profile names are case-sensitive and must match the .ini filename exactly (without the extension). Set the correct one with 3dm setup or by editing defaults.toml with 3dm edit-global-config.

This project requires 3DMake version X or newer. The min_3dmake_version key in 3dmake.toml is higher than your installed version. Run 3dm version to check your version, then update 3DMake. If you are the project author, lower min_3dmake_version if the feature requirement does not actually apply.


Build Errors

Source file src/main.scad does not exist. Either you are not in a 3DMake project directory, or model_name in your 3dmake.toml does not match an actual .scad file in src/. Run 3dm edit-model to create the file, or correct model_name.

Some needed libraries are not installed: <name> Run 3dm install-libraries to download and install the missing libraries listed in your 3dmake.toml libraries key. Run 3dm list-libraries to verify the library name is spelled correctly (names are lowercase).

OpenSCAD prints warnings but does not fail. Add strict_warnings = true to your 3dmake.toml to treat warnings as errors. This is recommended for all projects to catch issues like undefined variables and deprecated syntax early.

Build succeeds but STL looks wrong / has missing geometry. Run with --debug to see the full OpenSCAD output including all warnings:

3dm build --debug

Slicing Errors

Could not find overlay 'X' for profile 'Y'. The overlay file does not exist at overlays/Y/X.ini or overlays/default/X.ini. Run 3dm list-overlays to see what is available, or 3dm edit-overlay -o X to create it.

Could not fit the object outline on the build surface. The model is larger than the printer’s bed, or is being placed off-center. Check your model dimensions with 3dm info, verify your printer_profile is correct for your actual printer, and confirm 3dm_bed_center is set correctly in your profile if you have a non-standard bed.

Slicer produces unexpected print warnings. Run with --debug to see the full PrusaSlicer stdout output:

3dm slice --debug

Unknown print mode 'X'. print_mode in your config must be exactly one of: octoprint, bambu_lan, or bambu_connect. Check spelling in defaults.toml.

OctoPrint: ERROR: Authentication failed (401) Your octoprint_key is wrong or expired. In OctoPrint, go to Settings > Application Keys and generate a new key, then update defaults.toml via 3dm edit-global-config.

OctoPrint: ERROR: Could not connect to server Check that octoprint_host is correct and includes the protocol (http:// or https://). Verify OctoPrint is running and the machine running 3DMake is on the same network. Run 3dm test-connect for a detailed diagnosis.

Bambu: FTP or MQTT connection fails. Verify bambu_host is the printer’s current local IP (it may change if your router assigns IPs dynamically — consider setting a static IP for the printer). Check bambu_access_code on the printer screen under Settings > WLAN. Run 3dm test-connect for step-by-step diagnosis.

Bambu Connect mode: 3dm print with print_mode = "bambu_connect" does not connect directly to the printer. It packages your G-code into a .3mf file and opens the Bambu Connect desktop application via a URI handoff. Bambu Connect must be installed and running on your machine. 3dm test-connect will report that it cannot test this mode — this is expected.


General

Unknown action 'X' Action names are lowercase and use hyphens, not underscores (e.g. edit-model, not edit_model). Run 3dm help for the full list.

The action 'X' can only be used on its own You combined an isolated action with other actions. Isolated actions (edit-*, setup, new, version, help, test-connect, list-*, install-libraries) must be run alone.

Action 'X' cannot be followed by other actions You placed a last_in_chain action (image, info, preview) before other pipeline actions. These must be the final (or only) action in your command.

Cannot select a model name when using an input file --model / -m and a direct input file path are mutually exclusive. Use one or the other.

Multiple inputs not supported yet Only one input file can be passed per invocation. To process multiple files, use a shell loop.


OpenSCAD Tips & Conventions for 3DMake

Project Conventions

3DMake expects OpenSCAD source files in src/<model_name>.scad and writes STL output to build/<model_name>.stl. As long as you follow this layout (created automatically by 3dm new), everything works without extra configuration.

Parameterized Models

The most powerful pattern for 3DMake projects is a fully parameterized model where all key dimensions are defined as variables at the top of the file. This makes it trivial to create variants without duplicating code.

// src/box.scad
// All tunable parameters at the top

length    = 80;     // mm
width     = 50;     // mm
height    = 30;     // mm
wall      = 2.5;    // mm — wall thickness
tolerance = 0.2;    // mm — fit clearance for mating parts
fillet_r  = 1.5;    // mm — corner radius

// Model below uses only the variables above
module box_shell() {
    difference() {
        rounded_rect([length, width, height], r=fillet_r);
        translate([wall, wall, wall])
            cube([length-wall*2, width-wall*2, height]);
    }
}

box_shell();

Multi-Model Shared Parameters

For projects with multiple related models (e.g. a box and its lid), put shared dimensions in a separate include file:

// src/params.scad  — shared across all models
outer_length  = 80;
outer_width   = 50;
wall          = 2.5;
tolerance     = 0.2;
lid_height    = 8;
body_height   = 35;
// src/body.scad
include <params.scad>

difference() {
    cube([outer_length, outer_width, body_height]);
    translate([wall, wall, wall])
        cube([outer_length-wall*2, outer_width-wall*2, body_height]);
}
// src/lid.scad
include <params.scad>

cube([outer_length - tolerance*2, outer_width - tolerance*2, lid_height]);

Useful OpenSCAD Modules for 3D Printing

// Rounded rectangle (better bed adhesion, less stress concentration)
module rounded_rect(size, r=1) {
    hull() {
        for (x=[r, size[0]-r], y=[r, size[1]-r])
            translate([x, y, 0]) cylinder(r=r, h=size[2], $fn=32);
    }
}

// Countersunk screw hole (M3 example)
module m3_hole(depth=10, countersink=true) {
    cylinder(d=3.4, h=depth, $fn=24);
    if (countersink)
        translate([0, 0, depth-3.2])
            cylinder(d1=3.4, d2=6.5, h=3.2, $fn=24);
}

// Snap-fit clip tab
module snap_tab(length=10, width=4, height=3, overhang=0.8) {
    union() {
        cube([length, width, height]);
        translate([0, 0, height])
            linear_extrude(overhang, scale=[1, 1, 0])
                square([length, width]);
    }
}

$fn, $fa, $fs — Circle Resolution

OpenSCAD renders circles and cylinders as polygons. Control resolution with these special variables:

VariableMeaningRecommended
$fnFixed number of fragments32 for small circles, 64+ for large
$faMinimum angle per fragment (degrees)1 for smooth curves
$fsMinimum fragment size (mm)0.5 for print resolution
// Set globally at top of file for consistent quality
$fa = 1;
$fs = 0.4;    // Match your nozzle diameter

// Or set per-object for performance (preview fast, export high quality)
cylinder(r=10, h=5, $fn=64);

Tip: Use $fn=16 or $fn=24 during development for fast preview renders, then raise it to $fn=64 or higher before your final 3dm build for export.

Designing for Printability

Avoid overhangs steeper than 45° without supports. Use chamfers instead of horizontal overhangs where possible:

// ❌ Horizontal lip — needs supports
translate([0, 0, 10]) cube([20, 5, 2]);

// ✅ 45° chamfer — self-supporting
hull() {
    cube([20, 2, 10]);
    translate([0, 5, 8]) cube([20, 0.01, 2]);
}

Minimum feature sizes at 0.4mm nozzle:

FeatureMinimum
Wall thickness0.8mm (2× nozzle) — ideally 1.2mm+
Hole diameter2mm (smaller holes tend to close up)
Gap / clearance between parts0.2–0.3mm for sliding fit, 0.1mm for press fit
Text / embossed detail0.5mm depth, 4pt font minimum
Pin diameter2mm minimum for structural pins

Orientation matters. Layer lines are weakest in tension perpendicular to the print direction. Design critical stress paths to run parallel to layer lines, or use the orient action to auto-optimize placement.

Tolerance for fits. PLA typically needs 0.2–0.3mm clearance for a sliding fit between printed parts. PETG and ABS may need slightly more. Build a quick tolerance test into your workflow:

// Tolerance test — print this and measure which gap fits your printer
for (i=[0:4])
    translate([i*15, 0, 0])
        difference() {
            cube([12, 12, 5]);
            translate([6, 6, 0])
                cylinder(d=5 + i*0.1, h=5, $fn=32);
        }

Using OpenSCAD Libraries with 3DMake

Declare library dependencies in 3dmake.toml, then install them:

# 3dmake.toml
libraries = ["openscad-threads", "bosl2"]
3dm install-libraries    # Downloads and installs to config dir
3dm list-libraries       # Verify installation

Then use them in your .scad files normally:

// BOSL2 example
include <BOSL2/std.scad>

cuboid([20, 20, 10], rounding=2, edges="Z");
// openscad-threads example
use <threads.scad>

metric_thread(diameter=8, pitch=1.25, length=20);

Appendix B: Comprehensive Slicing Guide — All Major Slicers


This appendix covers settings, workflows, and troubleshooting for 7 major 3D printer slicers. Each slicer is represented with:

  • Recommended settings for beginners
  • Screen-reader-accessible settings explanation
  • Common troubleshooting
  • Accessibility features built-in
  • Command-line usage (for PowerShell integration)

Referenced in: Lessons 5 (Safety), 8 (Design), 10 (Verification)

Overview: What is Slicing?

Slicing converts a 3D model into printer instructions:

SCAD Design (bracelet_holder.scad)
   v
Export to STL (3D shape file)
   v
Load into Slicer
   v
Apply settings (temperature, speed, supports, etc.)
   v
Generate G-code (printer instructions)
   v
Send to Printer
   v
Physical part

Core Slicing Parameters (All Slicers Share These)

ParameterWhat It DoesTypical RangeImpact
Nozzle TempFilament melting heat200-250CToo cold -> weak; too hot -> oozing
Bed TempBuild plate heat50-110CHelps adhesion; prevents warping
Layer HeightZ-axis precision0.1-0.4mmFiner = slower, better detail
Print SpeedMovement velocity30-150 mm/sFaster = worse quality; slower = stronger
Infill %Interior density10-100%Higher = stronger + heavier
SupportTemporary scaffoldingOn/OffRequired for overhangs >45
Bed AdhesionFirst layer stickinessBrim/Raft/SkirtPrevents parts lifting mid-print

1. PrusaSlicer (Prusa)

Overview

  • Developer: Prusa Research (Czech company)
  • Platforms: Windows, Mac, Linux (open-source)
  • Best For: Beginner-friendly, excellent support, strong community
  • Download: https://www.prusa3d.com/page/prusaslicer_410/
  • Accessibility: Good font sizes, text-based profiles

Quick Setup for Beginners

Step 1: Install & Select Your Printer

1. Open PrusaSlicer
2. Go to "Help" -> "Check for Updates"
3. When prompted, select your printer model
4. Choose default profile (matches printer exactly)

Step 2: Load Your STL

1. Click "File" -> "Open STL Model"
2. Select your bracelet_holder.stl
3. Model appears in 3D view

Step 3: Essential Settings

These are the most important adjustments:

SettingLocationBeginner ValueWhy
Layer HeightPrint Settings0.15mmBalance speed & quality
InfillPrint Settings20%Enough strength; fast print
SupportPrint SettingsYes (if needed)For overhangs >45
Nozzle TempFilament Settings210CDefault for PLA
Bed TempFilament Settings60CStandard PLA adhesion
Print SpeedPrint Settings150 mm/sBalanced quality

Step 4: Preview & Export

1. Click "Slice now" (or G-code icon)
2. Left panel shows preview of each layer
3. Look for issues:
   - Supports covering entire model? (OK)
   - Model floating in air? (Not OK-likely error)
   - Top surface quality acceptable?
4. If satisfied, click "Export G-code"
5. Save to USB or send to printer

Accessible Parameter Explanations

When adjusting settings, use these descriptions to understand what each does:

Layer Height (0.1-0.4mm)

  • Lower (0.1mm): Smoother surface, more layers, slower (best for detail)
  • Higher (0.4mm): Faster, rougher surface (best for speed)
  • Recommendation: 0.15mm for balanced quality

Infill Percentage (10-100%)

  • 10%: Fast, uses less filament, weaker (good for prototypes)
  • 20%: Good balance (recommended for most prints)
  • 50%: Stronger, slower, heavier
  • 100%: Solid interior, strongest, slowest (waste of plastic)

Support Type

  • None: Fast, good surface finish, but risky if overhangs exist
  • Linear (Default): Good balance-easy to remove, provides support
  • Grid: Extra strong support, takes longer to remove

First Layer

  • Brim: Adds border to help adhesion (recommended for beginners)
  • Raft: Sacrificial platform (good if bed isn’t level)
  • Skirt: Just outline, doesn’t help adhesion (fastest)

Command-Line Usage (PowerShell Integration)

# Slice a model automatically with PrusaSlicer
$model = "C:\Models\bracelet_holder.stl"
$output = "C:\GCode\bracelet_holder.gcode"
$config = "default"  # Use default printer profile
# Run PrusaSlicer in batch mode
& "C:\Program Files\Prusa3D\PrusaSlicer\prusa-slicer.exe" `
    --load-config-file "$config" `
    --export-gcode "$output" `
    "$model"
Write-Host "Slicing complete: $output"

Troubleshooting

ProblemCauseSolution
First layer not stickingBed not levelBed leveling procedure in printer manual
Supports everywhereNo support type selectedChange to “Linear” or “Grid”
Nozzle drags through modelZ-offset too lowRaise Z-offset +0.1mm
Oozing strings between partsTemp too highLower nozzle temp 5-10C
Print breaks mid-wayAdhesion problemAdd brim; check bed level

2. Bambu Studio (Bambu Lab)

Overview

  • Developer: Bambu Lab (printer manufacturer)
  • Platforms: Windows, Mac, Linux
  • Best For: Modern X1-series printers, excellent speed, AMS support
  • Download: https://bambulab.com/en/download/studio
  • Accessibility: Good contrast, keyboard navigation

Quick Setup

Step 1: Create Account & Connect Printer

  1. Launch Bambu Studio
  2. Sign in with Bambu Lab account
  3. Select printer from network
  4. Studio auto-detects printer settings

Step 2: Load Model & Configure

  1. Drag STL into workspace
  2. Auto-arranges on bed plate
  3. Default profile applied automatically

Step 3: Key Settings (Bambu-Specific)

SettingDefaultAdjustmentWhy
AMS Multi-ColorOffOn (if AMS attached)Auto-switch filament
Auto-LevelingEnabledKeep OnBambu feature-very reliable
Nozzle Temp220CKeep unless specifiedBambu-optimized
Layer Height0.2mm0.15mm for detailBalance speed/quality
Bed Temp65C60C for PLAStandard adhesion

Step 4: Send to Printer

  1. Click “Prepare” (bottom right)
  2. Review preview
  3. Click “Send to Device”
  4. Printer receives over WiFi
  5. Start print from printer screen

Accessible Parameter Explanations

Auto-Leveling

  • Bambu printers automatically level the nozzle before every print
  • Explanation: Saves manual calibration; extremely reliable
  • For VI users: Provides confidence that bed is properly prepared

Filament Calibration

  • Before first use of new filament color, run “Filament Calibration”
  • This optimizes temperature and speed for that specific filament
  • Explanation: Ensures consistent color and strength

Multi-Material (AMS)

  • If you have Auto Material System (AMS):
    • Load up to 4 filament colors
    • Studio auto-switches during print
    • Explanation: Multi-color prints without manual intervention

Command-Line Usage (PowerShell)

# Slice with Bambu Studio (command-line interface)
$model = "C:\Models\bracelet_holder.stl"
$output = "C:\GCode\bracelet_holder.3mf"  # Bambu uses .3mf format
# Bambu Studio CLI
& "C:\Program Files\BambuStudio\bambu-studio.exe" `
    --output "$output" `
    "$model"
Write-Host "Slice saved: $output"
# Send to printer directly
# (Requires API key-see Bambu documentation)

Troubleshooting

ProblemCauseSolution
WiFi not connectingNetwork issueRestart printer WiFi; check SSID
AMS not switchingFilament not detectedLoad filament into AMS; recalibrate
Print quality inconsistentWrong filament typeRun filament calibration
Nozzle crashes on first layerAuto-level failedManually check nozzle height

3. Cura (Ultimaker)

Overview

  • Developer: Ultimaker (Dutch company, open-source)
  • Platforms: Windows, Mac, Linux
  • Best For: Broad printer support, user-friendly, good documentation
  • Download: https://ultimaker.com/software/ultimaker-cura
  • Accessibility: Clear UI, good contrast

Quick Setup

Step 1: Add Your Printer

  1. Launch Cura
  2. Go to “Settings” (top-right)
  3. Click “Printers” -> “Add Printer”
  4. Select your printer model from list
  5. Confirm network connection

Step 2: Load & Prepare Model

  1. Drag STL into workspace
  2. Model auto-scales if needed (confirm size)
  3. Right-click -> “Support” (if overhangs need support)

Step 3: Recommended Settings

SettingValueNotes
ProfileStandardGood balance for most prints
Layer Height0.2mmDefault; change to 0.15mm for detail
Infill20%100% waste for solid parts
Support Angle50Auto-generates support for overhangs
Build Plate AdhesionBrimHelps first layer stick
Nozzle Temp200CStandard PLA
Bed Temp60CStandard PLA

Step 4: Print

  1. Click “Slice” (bottom right)
  2. Review layer-by-layer preview
  3. Click “Print Over Network” or “Print to File”
  4. Model sends to printer or saves as .gcode

Accessible Settings Explanation

Combing Mode

  • Off: Nozzle retracts on every travel (quality)
  • All: Never retracts (faster, possible stringing)
  • Not in Skin: Smart compromise
  • For VI users: Retraction prevents nozzle oozing on visible surfaces

Z-Offset (Z Clearance)

  • Adjusts first-layer distance
  • Too low -> nozzle scrapes bed (bad)
  • Too high -> filament doesn’t stick (bad)
  • Correct -> thin line of plastic sticks to bed

Gradual Infill

  • Automatically reduces infill strength away from surface
  • Saves filament while maintaining strength
  • Explanation: The core doesn’t need to be solid

Command-Line Usage (PowerShell)

# Cura engine CLI (CuraEngine)
$model = "C:\Models\bracelet_holder.stl"
$output = "C:\GCode\bracelet_holder.gcode"
$config = "default.cfg"
# Requires Cura to be installed; command-line slicing
& "C:\Program Files\Ultimaker Cura\CuraEngine.exe" `
    -c "$config" `
    -o "$output" `
    "$model"
Write-Host "Sliced: $output"

Troubleshooting

ProblemCauseSolution
Model appears too small on bedScale wrongRight-click -> Scale to fit
Stringing between partsRetraction disabledEnable retraction in settings
Support doesn’t generateAuto-support offEnable “Generate Support”
Printer not foundNetwork/USB issueCheck connection; restart Cura

4. SuperSlicer (Modification of Prusa)

Overview

  • Developer: Community fork of PrusaSlicer
  • Platforms: Windows, Mac, Linux
  • Best For: Advanced users wanting more control than Prusa offers
  • Download: https://github.com/supermerill/SuperSlicer
  • Accessibility: Similar to Prusa, more advanced options

Key Differences from Prusa

FeaturePrusaSlicerSuperSlicer
Arachne EngineNoYes-better edges
Seam PositionLimited optionsFull control
Pressure EqualizationNoYes-better bridging
Stealth ModeNoYes-quieter/higher quality

When to Use SuperSlicer

  • Printing challenging geometries with tight tolerances
  • Need advanced surface finish control
  • Familiar with PrusaSlicer already and want more power

Quick Start

  1. Download SuperSlicer from GitHub
  2. Export profile from PrusaSlicer (if you have it)
  3. Import into SuperSlicer
  4. All settings are compatible with PrusaSlicer

Advanced Settings for SuperSlicer

Arachne Engine

  • Enables finer edges on walls
  • Results in cleaner, more accurate prints
  • Takes slightly longer to slice but worth it

Seam Positioning

  • Random: Hides seams (good for aesthetic)
  • Aligned: Consistent location (good for debugging)
  • Rear: Always at back (recommended)

Pressure Equalization

  • Helps with bridging (printing across gaps)
  • Reduces sagging on overhangs
  • Recommended: Enable for complex designs

5. OrcaSlicer (Modern Bamboo Alternative)

Overview

  • Developer: Community (independent open-source)
  • Platforms: Windows, Mac, Linux
  • Best For: Users who want Bambu features without Bambu printer
  • Download: https://github.com/SoftFever/OrcaSlicer
  • Accessibility: Modern UI, good keyboard support

Why Orca?

OrcaSlicer brings Bambu Studio’s best features to any printer:

  • Excellent defaults
  • Fast slicing
  • Good preview
  • Modern interface

Quick Setup

  1. Download OrcaSlicer
  2. Select your printer (not just Bambu models)
  3. Load STL
  4. Uses good defaults-usually ready to print

Key Settings

SettingValueWhy
Wall Loops2Strong walls, visible detail
Internal Solid Layer4Strength for brackets/connectors
Infill PatternGridBalanced strength
Line WidthAutoMatches nozzle diameter
Speed80 mm/sBalanced quality/speed

Accessible Features

Filament Manager

  • Track filament type, color, weight used
  • Explanation: Know when to buy new filament

Print Time Estimation

  • Accurate prediction of print duration
  • Updates during slicing

Material Presets

  • Pre-configured settings for common filaments
  • Just select material type; settings auto-apply

6. IdeaMaker (Raise3D)

Overview

  • Developer: Raise3D
  • Platforms: Windows, Mac, Linux
  • Best For: Raise3D printer users; advanced features
  • Download: https://www.raise3d.com/ideamaker
  • Accessibility: Professional UI, detailed settings

When to Use

  • Using a Raise3D printer (excellent multi-nozzle support)
  • Need industrial-strength slicing
  • Want dual-extrusion (2-color) printing

Quick Start

  1. Launch IdeaMaker
  2. Add printer (Raise3D models have built-in profiles)
  3. Load STL
  4. Adjust layer height and infill
  5. Slice and send to printer

Key Features

Dual Extrusion

  • Two nozzles = two colors in one print
  • Useful for: Bracelets (core + colored rim)
  • Requires: Coordinating two materials

Advanced Support

  • Tree support (uses less material)
  • Grid support (stronger for larger parts)

Print Balancing

  • Optimizes nozzle movement for efficiency
  • Reduces print time without sacrificing quality

7. Fusion 360 (CAD + Slicer)

Overview

  • Developer: Autodesk
  • Platforms: Windows, Mac
  • Best For: If you already use Fusion 360 for CAD
  • Download: https://www.autodesk.com/products/fusion-360
  • Accessibility: Integrated environment; good for learning CAD+Slicing together

Why Integrate CAD + Slicing?

Traditional workflow:

Design in CAD -> Export to STL -> Open in Slicer -> Slice -> Print

Fusion 360 workflow:

Design in Fusion -> Run Print Preparation -> Slice -> Print

Advantage: Stay in one program; no format conversion

Quick Start

  1. Design in Fusion 360 (or import STL)
  2. Select part
  3. Go to “3D Print” tab
  4. Click “Print Preparation”
  5. View auto-generated support and alignment
  6. Adjust layer height, infill, etc.
  7. Slice and export G-code

Integration with 3dMake

If using Fusion 360 for CAD:

  1. Export SCAD design to STL
  2. 3dm export-stl src/main.scad output/main.stl
  3. Then import into Fusion 360
  4. For more complex designs that need refinement

Universal Troubleshooting Guide

ProblemDiagnosisSolution
Print won’t stick to bedBed temperature too lowRaise bed temp +5C; check bed level
Bed not levelManual leveling procedure (printer manual)
Build plate dirtyClean with isopropyl alcohol
Nozzle hits model mid-printZ-offset wrongAdjust Z-offset; re-level bed
Model placed too low on bedUse “Arrange on Bed” tool in slicer
Supports won’t removeToo much support generatedReduce support density or angle
Support too strongReduce support material percentage
Stringy/OozingNozzle too hotReduce temp by 5-10C
Retraction disabledEnable retraction in settings
Travel speed too fastReduce travel speed
Layer shifting (X/Y)Belt tension offCheck belt tension (printer manual)
Stepper motor power issueFirmware issue-check printer logs
Model prints poorly but slices look goodFilament quality issueTry different filament batch
Nozzle cloggedUnclog nozzle (heat -> purge -> clean)
ScenarioBest SlicerWhy
I’m a beginnerPrusaSlicerClear defaults, excellent UI
I have a Bambu printerBambu StudioNative, best features
I have an UltimakerCuraOfficial support, broad compatibility
I have a Raise3DIdeaMakerOfficial, dual-extrusion support
I want advanced controlSuperSlicerMaximum customization
I want modern/fast slicingOrcaSlicerGreat defaults, any printer
I use Fusion 360 for CADFusion 360 Print PrepIntegrated workflow

PowerShell Integration: Batch Slicing

Slice Multiple Files Automatically

# Batch slice all SCAD designs in a project
$scadDir = "C:\Projects\3dMake\src"
$slicerConfig = "default.cfg"
$outputDir = "C:\Projects\3dMake\gcode"
# Find all SCAD files
$scadFiles = Get-ChildItem -Path $scadDir -Filter "*.scad" -Recurse
foreach ($scadFile in $scadFiles) {
    $stlFile = $scadFile.FullName -replace ".scad$", ".stl"
    $gcodeFile = Join-Path $outputDir ($scadFile.BaseName + ".gcode")
    # Export SCAD to STL
    Write-Host "Exporting: $($scadFile.Name)"
    & "C:\Program Files\OpenSCAD\openscad.exe" -o "$stlFile" "$($scadFile.FullName)"
    # Slice STL
    Write-Host "Slicing: $($scadFile.Name)"
    & "C:\Program Files\Prusa3D\PrusaSlicer\prusa-slicer.exe" `
        --load-config-file "$slicerConfig" `
        --export-gcode "$gcodeFile" `
        "$stlFile"
    Write-Host "Complete: $gcodeFile"
}
Write-Host "Batch slicing finished."

Monitor Printing Progress

# Connect to printer API and monitor print status
# (Requires printer to support API-check documentation)
$printerIP = "192.168.1.100"  # Your printer's IP
$printerPort = 8080            # Typical API port
# Get current print status
$status = Invoke-WebRequest -Uri "https://yourdolphin.com/supernova/" `
    -UseBasicParsing | ConvertFrom-Json
Write-Host "State: $($status.state.text)"
Write-Host "Progress: $($status.progress.completion)%"
Write-Host "Time remaining: $($status.progress.printTimeLeft) seconds"

Accessibility Best Practices for Slicing

Describing Sliced Models

# Use 3dm info to understand the slicer's output
# (Best practice: describe after slicing to verify settings)
3dm info output/bracelet_holder.stl
# Output includes:
# - Number of parts
# - Dimensions
# - Surface area
# - Volume

Testing Sliced Parts

  1. Weight Check:

    • Calculate expected weight from volume + material density
    • Compare to actual printed weight
    • Indicates if infill is correct
  2. Dimensional Check:

    • Use calipers to verify critical dimensions
    • Compare to SCAD parameters
    • Check tolerance stack-up
  3. Functional Test:

    • Assemble with other parts
    • Test strength by loading with known weight
    • Verify support removal didn’t damage part

Summary

This appendix provides:

  • [YES] 7 slicer workflows, settings, and troubleshooting
  • [YES] Accessible parameter explanations
  • [YES] Command-line integration for PowerShell
  • [YES] Comparison table for choosing a slicer
  • [YES] Batch processing automation examples
  • [YES] Accessibility best practices

Use this guide whenever you:

  • Start a new print
  • Switch slicers
  • Encounter quality issues
  • Want to automate slicing workflows
  • Need troubleshooting help

Appendix C: Material Properties and Selection Guide


This appendix covers material properties, characteristics, and selection criteria for 3D printing filaments. Each material includes:

  • Physical properties (strength, flexibility, temperature tolerance)
  • Printing parameters (nozzle temp, bed temp, speed)
  • Suitability for different projects
  • Accessibility considerations (measurement-based verification)
  • Cost/availability comparison

Referenced in: Lessons 5 (Safety), 6-10 (Projects), 11 (Customer Requirements)

Overview: Why Material Matters

The material you choose affects:

  • Strength: Can the part hold weight?
  • Flexibility: Will it bend or break?
  • Temperature: Can it withstand heat?
  • Durability: Will it last months or years?
  • Cost: Budget constraints?
  • Printability: Ease of use for beginners?
  • Appearance: Texture, color, finish?

The Material Selection Flowchart

What's the primary requirement?
+-- Strength & Detail?
    +-- PLA (best for beginners, detail)
        or PETG (stronger, tougher)
+-- Flexibility?
    +-- TPU/TPE (rubber-like)
+-- Heat Resistance?
    +-- ABS or Polycarbonate
+-- Transparency?
    +-- PETG or Polycarbonate
+-- Food Contact?
    +-- FDA-approved PETG or PLA
+-- Cost-Conscious?
    +-- PLA (cheapest, easiest)

1. PLA (Polylactic Acid)

Properties at a Glance

PropertyRatingNotes
Strength[3/5]Good for most projects; not for dynamic loads
Flexibility[1/5]Brittle; will snap under stress
Temperature Resistance[2/5]Softens around 60C; bad for hot environments
Ease of Printing[5/5]Most forgiving; best for beginners
Cost[5/5]Cheapest option (~$20/kg)
Appearance[5/5]Excellent surface finish; many colors
Availability[5/5]Available everywhere

Ideal Projects

  • [YES] Decorative pieces (jewelry, miniatures)
  • [YES] Enclosures/shells (light loads)
  • [YES] Prototype/mockups
  • [YES] Low-stress connector clips
  • [YES] Educational demonstrations
  • [NO] Load-bearing brackets
  • [NO] Hinges or flexing parts
  • [NO] Heat-resistant applications

Printing Parameters

ParameterValueTolerance
Nozzle Temp200C190-210C (varies by brand)
Bed Temp60C50-65C
Print Speed50 mm/s40-60 mm/s
Retraction5mm @ 40 mm/sYes, prevents stringing
Cooling Fan100%High cooling improves quality
First LayerSlower (25 mm/s)Ensures adhesion
Layer Height0.2mm0.1-0.3mm depending on detail

PLA Variants

Standard PLA

  • Most common, reliable
  • Best for beginners

PLA Pro / Enhanced PLA

  • Slightly stronger than standard PLA
  • Same temperature parameters
  • ~10% cost premium

Silk PLA

  • Glossy finish instead of matte
  • Same strength as standard PLA
  • Slightly slower to print

Marble or Color-Changing PLA

  • Visual effects
  • Same printing parameters
  • Mostly for aesthetics

Common Issues & Solutions

ProblemCauseSolution
Warping on cornersBed too hot or cooling too fastReduce bed temp to 50C; disable cooling for first layer
StringingTemp too highLower nozzle temp 5C
Poor layer adhesionNozzle too highLower Z-offset 0.1mm
Brittleness after printNormal for PLANot a problem; expected behavior
Nozzle clogs on retractionTemperature inconsistencyEnsure stable nozzle temp +/- 5C

Why PLA for This Course

PLA is recommended for all Lessons 1-11 because:

  1. Beginner-friendly: Most forgiving material
  2. Predictable: Consistent across different printers
  3. Cost-effective: Maximize printing volume on student budget
  4. Accessibility: Easier to troubleshoot for new users
  5. Safe: Non-toxic, low fume emission
  6. Available: Found at any 3D printing supplier

2. PETG (Polyethylene Terephthalate Glycol)

Properties at a Glance

PropertyRatingNotes
Strength[4/5]Tougher than PLA; better for load-bearing
Flexibility[2/5]Better than PLA but still primarily rigid
Temperature Resistance[3/5]Softens around 85C; better than PLA
Ease of Printing[4/5]Slightly more challenging than PLA
Cost[4/5]~$25/kg (slightly more than PLA)
Appearance[4/5]Good surface finish; slightly glossier than PLA
Availability[5/5]Widely available

When to Use PETG Instead of PLA

  • Functional brackets or mounts (where strength matters)
  • Parts that may be load-bearing (shelves, holders)
  • Outdoors/higher temperature environments
  • Parts requiring transparency (clear PETG available)
  • Better moisture resistance (vs. PLA)

Printing Parameters

ParameterValueTolerance
Nozzle Temp235C230-245C
Bed Temp80C75-85C
Print Speed50 mm/s40-60 mm/s (same as PLA)
Retraction4mm @ 40 mm/sSlightly less than PLA
Cooling Fan30-50%Less cooling than PLA
First LayerNormal (50 mm/s)Harder to adjust than PLA
Layer Height0.2mm0.1-0.3mm

Comparison: PETG vs. PLA

AspectPLAPETG
Nozzle Temp200C235C
Bed Temp60C80C
StrengthGoodBetter (20% stronger)
FlexibilityBrittleMore resilient
Heat Tolerance60C85C
EaseVery easyEasy (needs tweaking)
Cost$20/kg$25/kg
Outdoor UseNot idealBetter

Projects for PETG

  • [YES] Phone stand (needs strength)
  • [YES] Bracket or shelf support
  • [YES] Flexible clip (needs resilience)
  • [YES] Outdoor item
  • [YES] Clear enclosure (if using clear PETG)
  • [NO] Fine detail work (slightly courser finish)
  • [NO] Food-contact items (not food-safe unless specified)

3. ABS (Acrylonitrile Butadiene Styrene)

Properties at a Glance

PropertyRatingNotes
Strength[4/5]Similar to PETG; good impact resistance
Flexibility[3/5]More flexible than PETG
Temperature Resistance[5/5]Softens around 105C; best of common materials
Ease of Printing[2/5]Requires enclosure/heated bed; challenging
Cost[4/5]~$25-30/kg
Appearance[3/5]Rougher than PLA; requires post-processing
Availability[4/5]Good availability; not as universal as PLA

When to Use ABS

  • High-temperature environments (near heat sources)
  • Mechanical parts (gears, bearings)
  • Durability (parts lasting years)
  • Post-processing (can be sanded, glued, vapor-smoothed)
  • Professional applications (not toys/decorative)

Why ABS is Challenging

ABS requires:

  1. Enclosed environment: Minimize temperature fluctuations
  2. Heated bed: 100C+ (much higher than PLA)
  3. Controlled cooling: Too-fast cooling causes warping
  4. Ventilation: ABS emits fumes (acetone-like smell)

Printing Parameters

ParameterValueTolerance
Nozzle Temp240C230-250C
Bed Temp100C95-105C
EnclosureRequiredMaintains heat (reduces warping)
Print Speed40 mm/sSlower than PLA
Retraction3mm @ 30 mm/sVery short
Cooling Fan0%OFF (causes warping)
First LayerSlow (30 mm/s)Critical for adhesion

Projects for ABS

  • [YES] Mechanical components
  • [YES] Heat-resistant enclosure
  • [YES] Durable outdoor item
  • [YES] Professional prototypes
  • [NO] Beginner projects (too challenging)
  • [NO] Decorative/aesthetic work (not recommended)
  • [NO] Flexible parts

Accessibility Note

ABS is not recommended for this course because:

  1. Requires enclosed printer (expensive for beginners)
  2. High failure rate for inexperienced users
  3. Strong odor (ventilation concerns for some users)
  4. Requires extra equipment (acetone for post-processing)

4. TPU / TPE (Thermoplastic Polyurethane / Elastomer)

Properties at a Glance

PropertyRatingNotes
Strength[3/5]Good; impact-resistant
Flexibility[5/5]Very flexible; rubber-like
Temperature Resistance[3/5]Softens around 80C; moderate
Ease of Printing[3/5]Needs tweaking; flexible materials are tricky
Cost[3/5]~$30-40/kg (expensive)
Appearance[4/5]Smooth; feels good tactilely
Availability[4/5]Growing availability

What is TPU?

TPU is a flexible rubber-like plastic that:

  • Doesn’t crack when bent
  • Absorbs impact
  • Returns to original shape
  • Bridges the gap between plastic and rubber

Printing Parameters

ParameterValueTolerance
Nozzle Temp215C210-225C
Bed Temp60C50-70C
Print Speed20-30 mm/sVERY SLOW (flexibility needs time)
RetractionMinimal or Off0-1mm (flexible material doesn’t retract well)
Cooling Fan0%Off (material needs heat)
Line Width0.5mmWider than normal (flexible material bridges)

Projects for TPU

  • [YES] Phone case (needs flexibility + protection)
  • [YES] Flex joints / hinges
  • [YES] Gasket or seal
  • [YES] Shoe insert or orthotic
  • [YES] Tactile button (for accessibility)
  • [NO] Fine detail work (too stretchy)
  • [NO] Decorative items (usually not aesthetic)
  • [NO] Precision parts

Challenges with TPU

  1. Very slow printing: 5-10x slower than PLA
  2. Stringing: Flexible material tends to ooze
  3. Flexible bed needed: Standard beds may not work
  4. Post-processing difficult: Hard to sand/glue

Why TPU for Accessibility

TPU is excellent for accessibility because:

  • Can create tactile buttons/indicators
  • Flexible grips for ergonomic handles
  • Gaskets that don’t damage delicate equipment
  • Accessible because: Achievable by all users if given proper guidance

5. Polycarbonate (PC)

Properties at a Glance

PropertyRatingNotes
Strength[5/5]Extremely strong; impact-resistant
Flexibility[2/5]Rigid; similar to PETG
Temperature Resistance[5/5]Best; softens around 130C
Ease of Printing[2/5]Difficult; prone to warping
Cost[2/5]Most expensive (~$50+/kg)
Appearance[4/5]Transparent/translucent options
Availability[2/5]Limited; specialty supply

When to Use Polycarbonate

  • Highest strength required
  • Transparent/bullet-proof enclosure needed
  • Extreme temperature environment
  • Professional/industrial applications

Why Polycarbonate is Not for This Course

  1. Extreme difficulty (high failure rate)
  2. Very expensive (3-5x cost of PLA)
  3. Requires industrial-grade printer
  4. Post-processing complex

6. Nylon (PA)

Properties at a Glance

PropertyRatingNotes
Strength[5/5]Very strong; can be flexible
Flexibility[4/5]More flexible than ABS
Temperature Resistance[4/5]Good; softens around 120C
Ease of Printing[2/5]Difficult; very temperature-sensitive
Cost[3/5]~$30-40/kg
Appearance[3/5]Matte finish; less aesthetic than PLA
Availability[3/5]Growing but limited

Nylon Use Cases

  • [YES] Mechanical parts (gears, hinges)
  • [YES] Flexible connectors
  • [YES] Threads/screws
  • [YES] High-stress applications
  • [NO] Not for beginners

Material Comparison Table

MaterialNozzleBedStrengthFlexibilityHeatEaseCostBest For
PLA200C60C[3/5][1/5][2/5][5/5]$Beginners, detail
PETG235C80C[4/5][2/5][3/5][4/5]$$Functional parts
ABS240C100C[4/5][3/5][5/5][2/5]$$High-temp/mechanical
TPU215C60C[3/5][5/5][3/5][3/5]$$$Flexibility/tactile
PC280C110C[5/5][2/5][5/5][1/5]$$$$Extreme strength
Nylon250C85C[5/5][4/5][4/5][2/5]$$$Mechanical/flexible

Filament Quality Factors

Why Not All PLA is the Same

Diameter Tolerance

  • Good filament: +/- 0.03mm
  • Poor filament: +/- 0.1mm or worse
  • Impact: Inconsistent extrusion, layer quality varies

Dryness

  • PLA absorbs moisture from air
  • Wet filament = weak prints + bubbles
  • Solution: Store in sealed container with desiccant

Color Consistency

  • Good brands: Same color throughout
  • Poor brands: Color varies spool-to-spool

Impurities

  • Good: Minimal impurities
  • Poor: Visible specs/contaminants -> possible clogs

How to Check Filament Quality (Non-Visually)

  1. Weight Check

    Known: 1kg spool
    Weigh spool + filament
    Calculate remaining filament
    Should match spool markings
    
  2. Diameter Check

    Use caliper to measure multiple points
    Should be consistent +/- 0.03mm
    If varying, likely lower quality
    
  3. Dryness Test

    Feel texture: Should be smooth, not tacky
    Smell: Should be neutral (not musty)
    If wet, store in sealed container with desiccant
    
  4. Print Test

    Print small cube (20mm x 20mm x 20mm)
    Inspect surface: Smooth or bubbly?
    Weight: Does it match expected weight?
    

Storage & Maintenance

Proper Filament Storage

Temperature

  • Store between 15-25C
  • Avoid direct sunlight (fades color, degrades material)

Humidity

  • Keep below 40% humidity
  • Use desiccant packets in sealed containers
  • Change desiccant every 2-3 months

Organization

  • Label spools with: Material, color, date opened, approx. remaining
  • Store vertically or on spindle (prevents kinking)

Filament Degradation Signs

SignCauseSolution
Weak prints / breaking easilyFilament aged or wetReplace with fresh filament
Discoloration or spotsOxidation or contaminationNot usable; discard safely
Brittle or crumblyOverheated or UV damageNot usable; discard
Slight fading (color)UV exposureStill usable; just faded

Cost Analysis

Cost per Project

Material cost = (Filament weight used) x (Cost per kg)

Example: Bracelet holder
- Weight: 25 grams
- Material: PLA at $20/kg
- Cost: (25g / 1000g) x $20 = $0.50

vs. PETG at $25/kg: $0.625
vs. ABS at $30/kg: $0.75

Budget Tips

  1. Buy bulk: 5kg spool is cheaper per gram than 1kg
  2. Buy sales: 30-40% discounts common during sales
  3. Brand matters: Premium brands slightly more but more reliable
  4. Generic brands: Often acceptable if reviews are good
RankBrandKnown ForCostNotes
1PrusamentReliability, Prusa compatibility$$$Best; excellent support
2MatterHackersQuality, variety$$Very good; educational focus
3FillamentumEuropean quality$$Excellent; eco-friendly
4OvertureValue, consistency$Good budget option
5eSUNVariety, affordable$Decent; variable quality

Material Selection Decision Tree

START HERE: What's most important?

GOAL: Beginner success?
  YES - PLA (best choice)
  NO  - Next question

GOAL: Strength matters?
  YES - PETG or Nylon
  NO  - Next question

GOAL: Flexibility needed?
  YES - TPU (rubber-like)
  NO  - Next question

GOAL: High temperature?
  YES - ABS or Polycarbonate
  NO  - Next question

GOAL: Transparent?
  YES - Clear PETG or Polycarbonate
  NO  - Use PLA

FINAL CHOICE:
- If unsure, use PLA
- If needs strength, use PETG
- If needs flexibility, use TPU
- If needs heat, use ABS

PowerShell Integration: Track Material Usage

# Track filament usage across all projects
$materialLog = @"
ProjectName,Material,ColorName,WeightUsed(g),DatePrinted,Notes
"@
# Example entries
$materialLog += "`nBraceletHolder,PLA,NaturalWhite,25.3,2024-01-15,Final design"
$materialLog += "`nPhoneStand,PETG,Black,47.2,2024-01-16,Needs strength"
$materialLog += "`nKeycap,PLA,Red,12.5,2024-01-17,Prototype"
# Save to CSV
$materialLog | Out-File "C:\Projects\material-log.csv"
# Analyze usage
$materials = Import-Csv "C:\Projects\material-log.csv"
$totalWeight = ($materials | Measure-Object -Property "WeightUsed(g)" -Sum).Sum
$avgWeight = ($materials | Measure-Object -Property "WeightUsed(g)" -Average).Average
Write-Host "Total weight used: $totalWeight grams"
Write-Host "Average per project: $avgWeight grams"
# Calculate cost (PLA at $20/kg)
$costPerKg = 20
$totalCost = ($totalWeight / 1000) * $costPerKm
Write-Host "Estimated cost: $$($totalCost.ToString("F2"))"

Summary

Key Takeaways:

  1. Start with PLA: Best for learning; most forgiving
  2. Understand the tradeoffs: Strength vs. ease, cost vs. quality
  3. Match material to project: Decorative = PLA; functional = PETG
  4. Store properly: Desiccant, cool, dark location
  5. Track usage: Know what works for future projects
  6. Test before committing: Print small test on new filament

Recommended Progression:

  • Lessons 6-7: PLA (simplest)
  • Lessons 8-9: PLA or PETG (functional parts)
  • Lesson 10: PETG or TPU (testing materials)
  • Lesson 11: Student choice (depends on stakeholder requirements)

Appendix D: Tolerance Testing and Quality Assurance Matrix


This appendix provides measurement-based testing methodology for verifying that 3D-printed parts meet design specifications. It’s designed to be used non-visually-focusing on calipers, scales, and functional tests rather than visual inspection.

Referenced in: Lessons 8-10 (Complex Design, Troubleshooting, Mastery)

Overview: What is Tolerance?

Tolerance is the acceptable range of variation in dimensions:

Design spec:  Hole diameter = 6mm
Tolerance:    +/-0.5mm
Acceptable range:  5.5mm to 6.5mm
Actual print:  5.8mm [YES] (within tolerance)
or            7.2mm [NO] (exceeds tolerance)

Why Tolerance Matters

  1. Assembly: Parts must fit together
  2. Function: Fit too tight = stuck; too loose = falls apart
  3. Safety: Wrong tolerance = part failure
  4. Cost: Tight tolerance = slower, more waste

Essential Measurement Tools

1. Digital Calipers

What they measure:

  • Outside diameter (part width)
  • Inside diameter (hole width)
  • Depth

How to use non-visually:

  1. Gently close calipers until they barely touch the part
  2. Feel the resistance (should be light, not forced)
  3. Read digital display with audio feedback or manually
  4. Record three measurements at different locations
  5. Average the three measurements

Accuracy: +/-0.05mm (very precise for 3D printing)

2. Digital Scale (Kitchen Scale)

What it measures:

  • Part weight (indicates infill, material type)

How to use non-visually:

  1. Place part on scale
  2. Wait for reading to stabilize (1-2 seconds)
  3. Read digital display (in grams)
  4. Compare to expected weight

Accuracy: +/-1g (good enough for verification)

Why it matters:

  • Too light = infill too low or void inside part
  • Expected weight = indicates proper slicing

3. Test Jig / Go/No-Go Gauge

What it measures:

  • Pass/fail tolerance testing without calipers

How to make:

// Go/No-Go gauge for bracelet peg holes
// Tests if hole is within acceptable range
pegdiameter = 6;        // Design spec
tolerance = 0.5;         // Tolerance
godiameter = pegdiameter - tolerance;     // Min acceptable (5.5)
nogodiameter = pegdiameter + tolerance;  // Max acceptable (6.5)
module gogauge() {
  // Part should fit through this easily
  cylinder(h=10, r=godiameter/2);
}
module nogogauge() {
  // Part should NOT fit through this
  cylinder(h=10, r=nogodiameter/2);
}
// Test jig with both gauges
union() {
  translate([0, 0, 0]) gogauge();
  translate([0, 15, 0]) nogogauge();
}

Use non-visually:

  • Try inserting peg into go-gauge -> Should slide easily
  • Try inserting peg into no-go-gauge -> Should NOT fit
  • If both tests pass = tolerance correct

Quality Assurance Testing Matrix

Critical Dimensions to Test

Create a Test Plan before printing:

PartDimensionSpecToleranceHow to Test
Bracelet HolderBase width127mm+/-2mmMeasure with calipers (multiple points)
Peg diameter6mm+/-0.5mmTest fit with go/no-go gauge
Peg spacing8mm+/-1mmMeasure distance between pegs
Back wall height120mm+/-2mmMeasure with calipers
Phone StandSlope angle20+/-3Calculate from height/depth ratio
Weight capacity200g150-250gLoad test (see below)
StabilityN/APass/fail1-hour load test without tipping

Pre-Print Planning

Before slicing, define:

  1. Critical dimensions: Which measurements matter most?
  2. Acceptable range: What tolerance is realistic?
  3. Test method: How will you verify?
  4. Pass/fail criteria: What does “success” look like?

Example Plan for Phone Stand:

# Phone Stand - Quality Assurance Plan

## Critical Dimensions
1. Slope angle: 20 +/-3
2. Base width: 80mm +/-1mm
3. Stand height: 60mm +/-2mm

## Functional Tests
1. Stability: Hold 200g for 1 hour without tipping
2. Grip: Phone doesn't slide during tilt
3. Assembly: Back brace attaches without force

## Pass/Fail Criteria
[YES] PASS if:
- All dimensions within tolerance
- Phone holds weight for 1 hour
- No cracks or layer separation

[NO] FAIL if:
- Any dimension >2mm off spec
- Phone slides or part tips
- Visible cracks

Measurement Procedures

Procedure 1: Linear Dimension (Width, Height, Depth)

Equipment needed: Digital calipers

Steps:

  1. Place part on flat surface
  2. Position caliper jaws perpendicular to surface
  3. Gently close jaws until they just touch part
  4. Feel for light resistance (not forced)
  5. Read digital display
  6. Record measurement
  7. Repeat at 3 different locations
  8. Average the three readings
  9. Compare to design spec +/- tolerance

Example:

Design spec: 127mm (bracelet holder width)
Tolerance:   +/-2mm (acceptable: 125-129mm)
Measurements:
  Location 1: 126.8mm
  Location 2: 127.1mm
  Location 3: 126.5mm
  Average: 126.8mm [YES] (within tolerance)

Procedure 2: Hole or Peg Diameter

Equipment needed: Digital calipers, Go/No-Go gauges (optional)

Method A: Direct Measurement

  1. Insert caliper jaws into hole/around peg
  2. Adjust jaws to gently touch surfaces
  3. Feel for light resistance on both sides
  4. Read digital display (inside measurement mode)
  5. Record three measurements
  6. Average the readings

Method B: Go/No-Go Gauge

  1. Print test jigs (go & no-go gauges)
  2. Attempt to insert peg/hole into go-gauge -> Should slide through easily with light resistance
  3. Attempt to insert peg/hole into no-go-gauge -> Should NOT fit or fit with visible resistance
  4. If both pass -> dimension is acceptable

Example: Peg Diameter

Design spec: 6.0mm Tolerance: +/-0.5mm (acceptable: 5.5-6.5mm) Method A (Direct): Measurement 1: 5.9mm Measurement 2: 6.0mm Measurement 3: 5.8mm Average: 5.9mm [YES] Method B (Go/No-Go): Slides through go-gauge (5.5mm) -> [YES] Doesn’t fit no-go-gauge (6.5mm) -> [YES] Result: PASS

Procedure 3: Surface Finish / Layer Quality

Equipment needed: Caliper, ruler, touch/texture assessment

Step 1: Surface Texture

Run fingers/hand over surface: [YES] Smooth -> Good quality Slightly rough -> Acceptable [NO] Very rough/bumpy -> Quality issue

Step 2: Layer Line Visibility

Feel horizontal ridges (layer lines): [YES] Barely perceptible -> Good (0.2mm layers) Noticeable but even -> OK (0.25mm layers) [NO] Very pronounced -> Quality issue

Step 3: Dimensional Consistency

Measure thickness at multiple points:
  Design spec: 3mm wall thickness
  Measure at 5 locations
  Record all measurements
  All should be within +/-0.2mm of each other
  Example:
    Pt 1: 3.0mm
    Pt 2: 3.1mm
    Pt 3: 3.0mm
    Pt 4: 2.9mm
    Pt 5: 3.1mm
  Std Dev: 0.08mm [YES] (very consistent)

Procedure 4: Weight Verification (Confirms Infill)

Equipment needed: Digital scale

Step 1: Calculate Expected Weight

Expected weight = Volume x Density x Infill% For bracelet holder (PLA): Volume = 127mm x 80mm x 120mm = 1,219,200 mm = 1,219.2 cm PLA density = 1.24 g/cm Infill = 20% Expected weight = 1,219.2 x 1.24 x 0.20 = 302.4g Acceptable range: 290-315g (+/-5%)

Step 2: Measure Actual Weight

  1. Place part on digital scale
  2. Wait for reading to stabilize (1-2 seconds)
  3. Read display in grams
  4. Compare to expected weight

Step 3: Interpret Result

Actual WeightInterpretation
290-315g[YES] Correct infill, no internal voids
<280gInfill too low or significant voids
>320gInfill too high (was it supposed to be 20%?)

Functional Testing

Test 1: Load Testing (Strength)

Purpose: Verify part can hold weight without failure

Equipment needed:

  • Digital scale
  • Test weights (or books, water jugs)
  • Calipers (to check for deflection)

Procedure:

  1. Measure baseline dimensions (part unloaded) Baseline height: 60mm
  2. Place test weight on part Added weight: 200g
  3. Wait 5 minutes (allow part to settle)
  4. Measure dimensions again New height: 59.8mm Deflection: 0.2mm (acceptable)
  5. Observe for cracks (visual or tactile) No cracks: [YES]
  6. Remove weight and wait 5 minutes
  7. Measure dimensions again (should return to baseline) Height after unload: 60.0mm Recovery: Complete [YES] Result: PASS (part handles load without permanent deformation)

Acceptance Criteria for Phone Stand:

[YES] PASS if:

  • Deflection <0.5mm under 200g load
  • No cracks visible/felt
  • Full recovery after load removed [NO] FAIL if:
  • Deflection >1mm
  • Visible cracks
  • Permanent deformation after unload

Test 2: Assembly Testing

Purpose: Verify parts fit together as designed

Equipment needed:

  • Calipers
  • Go/No-Go gauges

Procedure for Multi-Part Assembly (e.g., Stackable Bins):

Part A (Bin body) dimensions:

  • Top opening: 50mm x 50mm +/-1mm
  • Wall thickness: 2mm +/-0.2mm Part B (Stacking rim) dimensions:
  • Base diameter: 50mm +/-0.5mm
  • Should nest inside Part A Test procedure:
  1. Measure Part A opening: 50.1mm [YES]
  2. Measure Part B base: 49.8mm [YES]
  3. Attempt to nest Part B into Part A -> Should fit with light resistance -> Feel for smooth insertion (no catching)
  4. Check for rocking (part should sit stable)
  5. Apply 500g load (simulate stacking) -> Should hold without slipping

Test 3: Durability Testing (Repeated Use)

Purpose: Verify part doesn’t fail after repeated cycles

Example: Phone Stand Tilt Cycles

  1. Record baseline dimensions
  2. Cycle 1: Place phone, tilt to max angle, remove
  3. Inspect for cracks or damage
  4. Repeat cycle 10 times
  5. Measure dimensions again
  6. Compare to baseline: Should be <0.1mm change If no damage after 10 cycles -> Durable [YES]

Tolerance Stack-Up (Multi-Part Designs)

When multiple parts are assembled, tolerances add:

Design: Part A opening: 50mm +/-0.5mm Part B base: 50mm +/-0.5mm Worst-case fit: Part A minimum: 49.5mm Part B maximum: 50.5mm Difference: 1.0mm (VERY TIGHT or won’t fit!) Solution: Increase tolerance on Part B to +/-0.3mm Part B minimum: 49.7mm Part B maximum: 50.3mm Now fits inside Part A: 49.5-50.5mm [YES]

Tolerance Stack-Up Calculation

For N parts in assembly:

Total tolerance = (tolerance + tolerance + ... + tolerance)
Example with 3 parts (each +/-0.5mm):
Total = (0.5 + 0.5 + 0.5)
      = 0.75
      = 0.87mm

Common Dimensional Problems & Fixes

ProblemTypical CauseHow to FixPrevent Next Time
Part too small (all dimensions off)Scale wrong in slicerScale STL up in CAD or slicerVerify scale before slicing
Holes too smallCompensation shrinkageIncrease hole diameter +0.5mmAdd shrinkage factor to design
Walls too thinLayer squishingCheck first layer height; may need recalibrationMeasure first layer thickness
Infill showing through (loose fill)Infill too lowIncrease infill % to 25-30%Recalculate for part type
Inconsistent across printNozzle clogging mid-printClean nozzle; check filament qualityUse quality filament; monitor print
Z-axis dimensions offZ-axis uncalibratedRun Z-calibration procedureCalibrate before critical prints
Dimensions change between printsThermal driftPrint in stable temperatureUse enclosed printer if possible

Testing Checklist Template

Print this checklist before starting a new project:

# Quality Assurance Checklist: [Project Name]

## Design Specs
- [ ] Part A width:  mm +/-  mm
- [ ] Part B height:  mm +/-  mm
- [ ] Hole diameter:  mm +/-  mm
- [ ] Assembly fit tolerance:  mm

## Pre-Print
- [ ] STL exported correctly
- [ ] Scale verified
- [ ] Supports configured
- [ ] Slice file reviewed

## Post-Print (Dimensional)
- [ ] Part A width measured (3 points): mm, mm, mm
  - [ ] Within tolerance? YES/NO
- [ ] Part B height measured (3 points): mm, mm, mm
  - [ ] Within tolerance? YES/NO
- [ ] Hole diameter measured (go/no-go): PASS/FAIL
- [ ] Part weight measured: g (expected: g +/-g)
  - [ ] Within expected weight? YES/NO

## Post-Print (Functional)
- [ ] Load test (if applicable): PASS/FAIL
- [ ] Assembly test: PASS/FAIL
- [ ] Surface quality acceptable: YES/NO
- [ ] No cracks or voids: YES/NO

## Result
- [ ] ACCEPT (all tests pass)
- [ ] REWORK (minor issue, can fix)
- [ ] REJECT (major issue, reprint)

## Notes
[Space for observations]

PowerShell Integration: Track Quality Metrics

# Track print quality across multiple projects
$qualityLog = @"
ProjectName,Date,Material,PartCount,DimensionsPass,FunctionalPass,Weight(g),Notes
"@
# Log entries
$qualityLog += "`nBraceletHolder,2024-01-15,PLA,1,PASS,PASS,302.1,Perfect fit"
$qualityLog += "`nPhoneStand,2024-01-16,PETG,2,PASS,PASS,487.3,Strong joints"
$qualityLog += "`nStackableBins,2024-01-17,PLA,3,FAIL,N/A,N/A,Holes too small reprint"
# Save to CSV
$qualityLog | Out-File "C:\Projects\quality-log.csv"
# Analyze pass/fail rate
$log = Import-Csv "C:\Projects\quality-log.csv"
$passCount = ($log | Where-Object { $.DimensionsPass -eq "PASS" }).Count
$totalCount = $log.Count
$passRate = ($passCount / $totalCount) * 100
Write-Host "Print success rate: $passRate%"
# Show recent failures
Write-Host "`nRecent issues:"
$log | Where-Object { $.DimensionsPass -eq "FAIL" } | Select-Object ProjectName, Notes

Accessibility-Focused QA Best Practices

Why Measurement-Based Testing Matters

Traditional visual QA (looking at surface finish, checking dimensions by eye) is inherently inaccessible. This appendix prioritizes:

  1. Caliper measurements: Objective, quantifiable
  2. Weight verification: Numerical result
  3. Functional testing: Pass/fail criteria
  4. Go/No-Go gauges: Tactile pass/fail
  5. Test jigs: Can be shared/standardized

Screen Reader Integration

When documenting QA results:

[YES] GOOD: "Bracket width measured 49.8mm (spec 50+/-1mm)"
[NO] AVOID: "Bracket looks good" (not measurable)
[YES] GOOD: "Part weighs 298g (spec 300+/-10g)"
[NO] AVOID: "Feels about right" (subjective)
[YES] GOOD: "Slides through go-gauge, blocks no-go-gauge"
[NO] AVOID: "Hole looks the right size" (visual only)

Documentation Template (Accessible)

## Part: Bracelet Holder Peg (Test Date: Jan 15, 2024)

### Dimensional Verification
| Dimension    | Specification  | Measurement 1 | Measurement 2 | Measurement 3 | Average | Result     |
|--------------|----------------|---------------|---------------|---------------|---------|------------|
| Peg Diameter | 6.0 +/- 0.5mm  | 5.9mm         | 6.0mm         | 5.8mm         | 5.9mm   | [YES] PASS |
| Peg Length   | 25.0 +/- 0.5mm | 25.1mm        | 25.0mm        | 25.0mm        | 25.03mm | [YES] PASS |

### Functional Test
- [x] Slides into bracelet loop easily (no forcing)
- [x] No cracks visible or felt
- [x] Survives 1-hour load test with 20 bracelets
- [x] No permanent deformation after load removed

### Overall Result
[YES] PASS - All dimensions within tolerance; functionally sound

Summary

Key Principles:

  1. Plan before printing: Define tolerances and test methods
  2. Measure precisely: Use calibrated tools (digital calipers, scale)
  3. Test functionally: Will parts assemble and work?
  4. Document quantitatively: Use numbers, not adjectives
  5. Iterate based on data: If test fails, adjust design or process

When to Use Each Test:

SituationRecommended Test
Prototype/mockupLinear dimensions only
Assembly with other partsTolerance stack-up analysis
Load-bearing partFunctional load test
Repeated-use itemDurability cycling test
Multi-part designAssembly fit test

Accessibility Reminder:

All QA testing in this appendix is measurement-based and non-visual, making it equally accessible to all users. The goal is objective, quantifiable verification-not subjective assessment.


Appendix E: Advanced OpenSCAD Concepts


This appendix covers specialized topics for experienced users seeking to tackle complex parametric designs. These are optional topics not required for foundational mastery but valuable for professional application development.

Topic 1: Gears and Mechanical Components

Gears are one of the most challenging parametric designs, requiring careful calculation of tooth geometry. Understanding gear mathematics enables creation of mechanical systems-power transmission, speed reduction, or precise positioning.

Gear Terminology

  • Pitch Diameter (PD): The reference diameter for meshing calculations
  • Module: PD divided by tooth count; determines tooth size
  • Pressure Angle: Typically 20deg or 14.5deg; affects tooth shape and strength
  • Clearance: Space between teeth to allow smooth meshing
  • Backlash: Intentional gap to prevent binding at tolerance extremes

Simple Involute Gear Algorithm

// Simplified gear with circular teeth (adequate for most 3D prints)
function gear_module(pitch_diameter, teeth_count) = pitch_diameter / teeth_count;
module simple_gear(pitch_diameter, teeth_count, bore_diameter, thickness) {
  module_m = gear_module(pitch_diameter, teeth_count);
  outer_diameter = pitch_diameter + 2 * module_m;
  tooth_angle = 360 / teeth_count;
  difference() {
    // Main gear body
    cylinder(r=outer_diameter/2, h=thickness, $fn=teeth_count*4);
    // Center bore
    cylinder(r=bore_diameter/2, h=thickness + 2);
  }
  // Add teeth as small protrusions
  for (i = [0:teeth_count-1]) {
    angle = i * tooth_angle;
    translate([
      (pitch_diameter/2 + module_m/2) * cos(angle),
      (pitch_diameter/2 + module_m/2) * sin(angle),
      0
    ])
      rotate([0, 0, angle])
        cube([module_m * 0.8, module_m, thickness], center=true);
  }
}
// Create meshing gear pair
module gear_pair_demo() {
  // Gear 1: 20 teeth, 40mm pitch diameter
  simple_gear(40, 20, 8, 10);
  // Gear 2: 30 teeth, positioned to mesh
  center_distance = (40 + 60) / 4;  // Sum of radii
  translate([center_distance, 0, 0])
    simple_gear(60, 30, 8, 10);
}
gear_pair_demo();

Practical Application: Servo Gearbox

// Parametric servo gearbox with 3:1 reduction
module servo_gearbox(motor_torque, reduction_ratio, bore_size) {
  // Input gear (motor)
  input_teeth = 12;
  input_pd = 30;
  // Output gear (load)
  output_teeth = input_teeth * reduction_ratio;
  output_pd = input_pd * reduction_ratio;
  // Gearbox housing
  housing_size = output_pd + 40;
  difference() {
    // Main box
    cube([housing_size, housing_size, 30]);
    // Interior chamber
    translate([20, 20, 5])
      cube([housing_size - 40, housing_size - 40, 25]);
  }
  // Mount input gear
  translate([housing_size/4, housing_size/2, 15]) {
    simple_gear(input_pd, input_teeth, bore_size, 15);
    // Motor coupling
    cylinder(r=bore_size/2, h=5);
  }
  // Mount output gear
  translate([3*housing_size/4, housing_size/2, 15])
    simple_gear(output_pd, output_teeth, bore_size, 15);
}
servo_gearbox(10, 3, 5);

Belt and Pulley Systems

// Timing pulley with tooth grooves
module timing_pulley(bore_diameter, pitch_diameter, teeth_count, width) {
  module_m = pitch_diameter / teeth_count;
  tooth_height = module_m * 0.3;
  difference() {
    // Main pulley body
    cylinder(r=pitch_diameter/2 + tooth_height/2, h=width);
    // Center bore
    cylinder(r=bore_diameter/2, h=width + 2);
    // Tooth grooves
    for (i = [0:teeth_count-1]) {
      angle = i * (360 / teeth_count);
      rotate([0, 0, angle])
        translate([pitch_diameter/2, -module_m*0.3, 0])
          cube([module_m * 0.6, module_m * 0.6, width], center=true);
    }
  }
}
// Belt drive demonstration
module belt_drive_system() {
  // Motor pulley (input)
  timing_pulley(5, 20, 16, 10);
  // Load pulley (output) - positioned for belt routing
  translate([80, 0, 0])
    timing_pulley(5, 40, 32, 10);
}
belt_drive_system();

Topic 2: Batch Processing and Statistical Analysis

Professional applications often generate many variants and need to analyze results. Batch processing enables systematic exploration of parameter spaces.

Parameter Sweep Generation

// Generate models with all combinations of parameters
// Define parameter ranges
wall_thicknesses = [1, 1.5, 2, 2.5, 3];
part_sizes = [20, 30, 40, 50];
materials = ["pla", "petg", "nylon"];
// Theory: Generate 5 x 4 x 3 = 60 variants automatically
// In practice, export each to separate STL for analysis

Statistical Summary Generation Script

@echo off
rem analyze_batch.bat - Analyze batch results (CMD / Batch)
setlocal enableextensions enabledelayedexpansion
set "OUTPUT_DIR=batch_results"
set "REPORT_FILE=batch_analysis.csv"
echo Part,Wall,Size,File_Size_KB,Est_Print_Time_min,Est_Weight_g > "%REPORT_FILE%"

for %%w in (1 2 3) do (
  for %%s in (20 30 40 50) do (
    set "SCAD_FILE=part_%%s_wall%%w.scad"
    set "STL_FILE=%OUTPUT_DIR%\%%~nSCAD_FILE.stl"
    "C:\Program Files\OpenSCAD\openscad.exe" -D "part_size=%%s" -D "wall=%%w" -o "%OUTPUT_DIR%\part_%%s_wall%%w.stl" src\main.scad
    if exist "%OUTPUT_DIR%\part_%%s_wall%%w.stl" (
      for /f "usebackq" %%F in (`powershell -NoProfile -Command "(Get-Item -Path '%OUTPUT_DIR%\part_%%s_wall%%w.stl').Length"`) do set FILE_BYTES=%%F
      set /a FILE_KB=FILE_BYTES / 1024
      set /a EST_TIME=(FILE_KB / 1024) * 60
      set /a EST_WEIGHT=FILE_KB / 1024
    ) else (
      set FILE_KB=0
      set EST_TIME=0
      set EST_WEIGHT=0
    )
    echo part_%%s_wall%%w,%%w,%%s,!FILE_KB!,!EST_TIME!,!EST_WEIGHT!>>"%REPORT_FILE%"
  )
)
endlocal
echo Analysis complete. Results in %REPORT_FILE%
# analyze_batch.ps1 - Analyze batch results (PowerShell)
$OutputDir = "batch_results"
$ReportFile = "batch_analysis.csv"
"Part,Wall,Size,File_Size_KB,Est_Print_Time_min,Est_Weight_g" | Out-File -FilePath $ReportFile -Encoding utf8

foreach ($wall in @(1.0,1.5,2.0,2.5,3.0)) {
  foreach ($size in @(20,30,40,50)) {
    $scad = "part_${size}_wall${wall}.scad"
    $stl = Join-Path $OutputDir ("{0}.stl" -f ([System.IO.Path]::GetFileNameWithoutExtension($scad)))
    & "C:\Program Files\OpenSCAD\openscad.exe" -D ("part_size={0}" -f $size) -D ("wall={0}" -f $wall) -o $stl src\main.scad
    if (Test-Path $stl) {
      $bytes = (Get-Item $stl).Length
      $kb = [math]::Round($bytes / 1KB, 2)
      $est_time = [math]::Round(($kb / 1024) * 60, 2)
      $est_weight = [math]::Round($kb / 1024, 2)
    } else {
      $kb = 0; $est_time = 0; $est_weight = 0
    }
    "{0},{1},{2},{3},{4},{5}" -f ("part_{0}_wall{1}" -f $size,$wall), $wall, $size, $kb, $est_time, $est_weight | Out-File -FilePath $ReportFile -Append -Encoding utf8
  }
}
Write-Host "Analysis complete. Results in $ReportFile"
#!/bin/bash
# analyze_batch.sh - Analyze batch results statistically

OUTPUT_DIR="batch_results"
REPORT_FILE="batch_analysis.csv"

echo "Part,Wall,Size,File_Size_KB,Est_Print_Time_min,Est_Weight_g" > "$REPORT_FILE"

for wall in 1.0 1.5 2.0 2.5 3.0; do
  for size in 20 30 40 50; do
    # Generate model
    SCAD_FILE="part_${size}_wall${wall}.scad"
    STL_FILE="$OUTPUT_DIR/${SCAD_FILE%.scad}.stl"
    
    # Export to STL
    openscad -D "part_size=$size" -D "wall=$wall" \
      -o "$STL_FILE" src/main.scad
    
    # Get file size
    FILE_SIZE=$(stat -c%s "$STL_FILE" 2>/dev/null | awk '{print $1/1024}')
    
    # Estimate print time (rough: 1 hour per MB)
    EST_TIME=$((FILE_SIZE / 1024 * 60))
    
    # Estimate weight (rough: 1g per MB for PLA)
    EST_WEIGHT=$((FILE_SIZE / 1024))
    
    # Log results
    echo "part_${size}_wall${wall},$wall,$size,$FILE_SIZE,$EST_TIME,$EST_WEIGHT" >> "$REPORT_FILE"
  done
done

echo "Analysis complete. Results in $REPORT_FILE"

Data-Driven Design Selection

// Load results and select optimal configuration
// wall=2.0mm gives best balance of strength/weight for most sizes
function optimal_configuration(target_size, priority) =
  priority == "strength" ? 3.0 :
  priority == "speed" ? 1.0 :
  priority == "balanced" ? 2.0 :
  2.0;  // Default
module batch_optimized_part(size, priority) {
  wall = optimal_configuration(size, priority);
  echo(str("Generating optimized part: size=", size, " wall=", wall, " priority=", priority));
  // Create part with optimal parameters
  difference() {
    cube([size, size, size]);
    translate([wall, wall, wall])
      cube([size - 2*wall, size - 2*wall, size]);
  }
}
// Generate three variants with different priorities
batch_optimized_part(40, "strength");    // thickest walls
translate([60, 0, 0]) batch_optimized_part(40, "speed");    // thinnest walls
translate([120, 0, 0]) batch_optimized_part(40, "balanced"); // medium walls

Topic 3: Performance Optimization

Complex models can take hours to render. Strategic optimization keeps iteration cycles fast.

Measuring Render Performance

# Time how long rendering takes
time openscad -o output.stl -D "quality=32" src/main.scad
# Output: real 5m 32s, user 5m 28s, sys 0m 2s

Resolution Parameter Strategy

// Use lower resolution during development, high during export
quality = $preview ? 16 : 64;  // 16 segments in preview, 64 in export
module efficient_sphere(radius) {
  sphere(r=radius, $fn=quality);
}
// In array operations, efficiency matters most
module circular_array(radius, count) {
  for (i = [0:count-1]) {
    angle = (360 / count) * i;
    x = radius * cos(angle);
    y = radius * sin(angle);
    translate([x, y, 0])
      efficient_sphere(5);  // Uses quality parameter
  }
}
circular_array(30, 100);  // 100 spheres: slow with quality=64!

Cache Complex Calculations

// Pre-compute expensive calculations outside loops
// SLOW: Recalculates sin/cos for every iteration
module slow_spiral() {
  for (i = [0:200]) {
    angle = i * 2;
    x = 40 * cos(angle);
    y = 40 * sin(angle);
    z = i * 0.5;
    translate([x, y, z])
      sphere(r=1);
  }
}
// FAST: Pre-compute positions, then use them
spiral_positions = [for (i = [0:200]) [
  40 * cos(i * 2),
  40 * sin(i * 2),
  i * 0.5
]];
module fast_spiral() {
  for (pos = spiral_positions)
    translate(pos)
      sphere(r=1);
}
// Use the fast version
fast_spiral();

Simplification During Preview

// Complex model that simplifies in preview mode
module detailed_model() {
  if ($preview) {
    // Simplified version for fast preview
    cube([100, 100, 50]);
  } else {
    // Detailed version for export
    difference() {
      cube([100, 100, 50]);
      // Complex inner geometry
      for (x = [10:10:90])
        for (y = [10:10:90])
          translate([x, y, 20])
            cylinder(h=15, d=3, $fn=32);
    }
  }
}
detailed_model();

Profile-Driven Optimization

#!/bin/bash
# profile_render.sh - Identify slow rendering hotspots

echo "Profiling render performance..."

for fn_value in 8 16 32 64 128; do
  echo ""
  echo "Testing with \$fn=$fn_value..."
  
  /usr/bin/time -v openscad -D "fn=$fn_value" \
    -o test_$fn_value.stl src/main.scad 2>&1 | \
    grep "Maximum resident set size"
done

Topic 4: Print Orientation and Support Structure Algorithms

Strategic orientation dramatically affects support material, print time, and surface quality.

Strength Orientation Analysis

// Different orientations affect strength differently
// SCENARIO: Bracket with cantilever load
module bracket() {
  difference() {
    cube([50, 100, 10]);
    translate([25, 50, 5]) cylinder(r=5, h=10);
  }
}
// Orientation A: Lay flat (XY plane) - WEAK for cantilever
echo("Orientation A: Flat - Low strength for cantilever");
bracket();
// Orientation B: Stand tall (Z axis) - STRONG for cantilever
translate([70, 0, 0]) {
  echo("Orientation B: Tall - High strength for cantilever");
  rotate([90, 0, 0]) bracket();
}
// Orientation C: Diagonal - MODERATE strength
translate([0, 150, 0]) {
  echo("Orientation C: Diagonal - Moderate strength");
  rotate([45, 0, 0]) bracket();
}

Support Material Minimization

// Design features to reduce supports needed
// POOR: Overhanging feature needs extensive supports
module poor_design() {
  cube([50, 50, 50]);
  translate([25, 25, 50])
    cube([30, 30, 10]);  // 30mm overhang!
}
// GOOD: Bridge angle keeps overhang under 45deg
module good_design() {
  cube([50, 50, 50]);
  // Add ramp instead of overhang
  translate([20, 20, 50])
    rotate([20, 0, 0])
      cube([30, 30, 10]);
}
// Compare
poor_design();
translate([80, 0, 0])
  good_design();

Bridge Span Calculation

// Calculate maximum unsupported span for given material/settings
function max_bridge_span(material) =
  material == "pla" ? 10 :
  material == "petg" ? 12 :
  material == "nylon" ? 15 :
  material == "abs" ? 8 :
  10;  // Default
module bridged_connector(material, gap_width) {
  max_span = max_bridge_span(material);
  if (gap_width <= max_span) {
    echo(str("Bridge OK: gap ", gap_width, "mm fits within ", max_span, "mm limit"));
    // Create part with bridge
    union() {
      cube([50, 10, 10]);  // Side A
      translate([gap_width, 0, 0])
        cube([50, 10, 10]);  // Side B
      // Bridge connecting them
      translate([0, 5, 10])
        cube([gap_width + 100, 2, 1]);
    }
  } else {
    echo(str("ERROR: gap ", gap_width, "mm exceeds ", max_span, "mm max bridge span"));
  }
}
bridged_connector("pla", 8);      // OK: 8 < 10
// bridged_connector("pla", 15);  // ERROR: 15 > 10

Slicing Parameter Calculation

// Calculate optimal slicing parameters based on geometry
function recommended_layer_height(nozzle_diameter, quality_priority) =
  quality_priority == "fast" ? nozzle_diameter * 0.75 :
  quality_priority == "balanced" ? nozzle_diameter * 0.5 :
  quality_priority == "detailed" ? nozzle_diameter * 0.25 :
  nozzle_diameter * 0.5;
function recommended_infill(structural_load, safety_factor) =
  structural_load < 1 ? 10 :    // Decorative: minimal fill
  structural_load < 5 ? 20 :    // Light duty: low fill
  structural_load < 20 ? 50 :   // Medium duty: standard fill
  100;                           // High duty: solid
module optimized_part(
  nozzle_0p4,
  quality_priority,
  structural_load,
  safety_factor
) {
  layer_h = recommended_layer_height(nozzle_0p4, quality_priority);
  infill_pct = recommended_infill(structural_load, safety_factor);
  echo(str("Recommended layer height: ", layer_h, "mm"));
  echo(str("Recommended infill: ", infill_pct, "%"));
  // Create part
  cube([50, 50, 30]);
}
optimized_part(0.4, "detailed", 15, 2);

Topic 5: Recursive Function Patterns

Recursion enables elegant solutions to problems with self-similar structure: trees, fractals, nested components.

Basic Recursive Pattern

// Tree structure: branches recursively smaller
function tree_depth(level) = level > 0 ? level + tree_depth(level - 1) : 0;
// Calculate: tree_depth(5) = 5 + 4 + 3 + 2 + 1 = 15
result = tree_depth(5);
echo(result);  // Prints: 15
// Recursive tree drawing
module tree_branch(length, angle, recursion_depth) {
  if (recursion_depth > 0) {
    // Draw this branch
    rotate([angle, 0, 0])
      cube([2, 2, length]);
    // Recursively draw sub-branches
    translate([0, 0, length])
      rotate([-angle/2, 0, 0])
        tree_branch(length * 0.7, angle, recursion_depth - 1);
    translate([0, 0, length])
      rotate([angle/2, 0, 0])
        tree_branch(length * 0.7, angle, recursion_depth - 1);
  }
}
tree_branch(30, 25, 4);  // Tree with 4 levels of recursion

Fractal Generation

// Sierpinski Triangle fractal
function sierpinski_triangle(size, depth) =
  depth == 0 ?
    [[0, 0], [size, 0], [size/2, size * sqrt(3)/2]] :
    // Recursive case: three smaller triangles at corners
    concat(
      sierpinski_triangle(size/2, depth - 1),
      sierpinski_triangle(size/2, depth - 1),
      sierpinski_triangle(size/2, depth - 1)
    );
// Create 3D fractal structure
module fractal_spiral(base_size, depth, height_per_level) {
  if (depth > 0) {
    // Create current level
    cube([base_size, base_size, 5], center=true);
    // Recursively create smaller level on top
    translate([0, 0, height_per_level])
      scale([0.6, 0.6, 1])
        fractal_spiral(base_size, depth - 1, height_per_level);
  }
}
fractal_spiral(40, 5, 10);  // 5-level spiral

Nested Component Assembly

// Russian doll boxes: each box contains a smaller copy
module russian_doll(size, wall, nesting_depth) {
  if (nesting_depth > 0) {
    // Current level: hollow box
    difference() {
      cube([size, size, size]);
      translate([wall, wall, wall])
        cube([size - 2*wall, size - 2*wall, size - wall]);
    }
    // Recursively place next smaller doll inside
    interior_size = size - 4*wall;
    translate([2*wall, 2*wall, wall])
      russian_doll(interior_size, wall, nesting_depth - 1);
  } else {
    // Smallest doll (solid)
    cube([size, size, size]);
  }
}
russian_doll(60, 2, 4);  // 4 nested boxes

Performance Considerations

// Recursion can be expensive - monitor depth
// EFFICIENT: Tail recursion (result computed immediately)
function sum_to(n, accumulator) =
  n == 0 ? accumulator :
  sum_to(n - 1, accumulator + n);
result = sum_to(100, 0);  // Computes: 5050
// INEFFICIENT: Deep recursion without optimization
function fibonacci(n) =
  n <= 1 ? n :
  fibonacci(n-1) + fibonacci(n-2);
// fibonacci(20) recalculates sub-problems thousands of times
// Don't use for depth > 20 without memoization
// BETTER: Use iteration where possible
function fibonacci_iter(n) =
  let(
    fib = [for (i = [0:n])
      i <= 1 ? i :
      let(prev = [for (j = [0:i-1]) i==j ? 1 : i==j+1 ? 0 : 0])
        1  // Placeholder
    ]
  ) fib[n];

Practical Example: Cable Management

// Recursive cable tray with branching paths
module cable_tray(width, depth, height, levels, branch_angle) {
  if (levels > 0) {
    // Main tray section
    difference() {
      cube([width, depth, height]);
      translate([2, 2, 2])
        cube([width - 4, depth - 4, height - 2]);
    }
    // Left branch (recursively smaller)
    translate([-width/2, 0, height])
      rotate([0, 0, -branch_angle])
        cable_tray(width * 0.6, depth, height, levels - 1, branch_angle);
    // Right branch
    translate([width/2, 0, height])
      rotate([0, 0, branch_angle])
        cable_tray(width * 0.6, depth, height, levels - 1, branch_angle);
  }
}
cable_tray(40, 10, 5, 3, 30);  // 3-level branching cable tray

Summary: When to Use Each Advanced Technique

TechniqueUse CaseComplexityPerformance
GearsMechanical power transmissionHighMedium
Batch ProcessingDesign space explorationMediumDepends on scope
Performance OptimizationReducing render timeMediumHigh payoff
Orientation AnalysisStrength optimizationMediumSimulation cost
RecursionFractal/nested structuresHighCan be expensive

References and Further Learning

For Educators and Students

These advanced topics are intended for:

  • Experienced users tackling professional applications
  • Specialized problem domains (robotics, mechanical design, etc.)
  • Research and optimization work
  • Custom library and framework development

For accessibility:

  • All recursive examples include base cases clearly marked
  • Each section provides simplified versions before advanced variants
  • Code comments explain both “what” and “why”
  • Practical examples show real-world applications
  • Performance considerations documented to prevent frustration

  1. Logan Library Cytiva STEM Makerspace.

  2. Utah STEM Action Center – Innovation Hub Network. ↩2 ↩3 ↩4

  3. Salt Lake City Public Library Creative Lab.

  4. Salt Lake County Library Create Spaces.

  5. University of Utah – Marriott Library ProtoSpace & 3D Printing.

  6. Washington County Library – Sid Atkin Makerspace.

  7. Weber County Library Makerspaces.

  8. https://www.nationofmakers.us/find-a-maker-organization

  9. https://makerspace.com/directory/ ↩2 ↩3

  10. https://makerspacedir.com/

  11. https://www.poidata.io/report/makerspace/united-states ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21 ↩22 ↩23 ↩24 ↩25 ↩26 ↩27 ↩28 ↩29 ↩30 ↩31 ↩32 ↩33 ↩34 ↩35 ↩36 ↩37 ↩38 ↩39 ↩40 ↩41 ↩42 ↩43

  12. https://workmakecreate.com/ ↩2

  13. https://www.globalspec.com/local/6383/C_US ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12

  14. https://makerspace.com/ ↩2 ↩3 ↩4

  15. https://www.makerdirectory.com/makerspace-directory/

  16. https://www.maker-works.com/local-makerspaces

Back Matter — Complete Reference

Supplementary reference material for Accessible 3D Printing with OpenSCAD and 3dMake. These sections are designed for lookup rather than linear reading — consult them as needed throughout the curriculum.


Contents

SectionTitlePurpose
Technical Reference and TroubleshootingSystems architecture, CLI reference, and fault-by-fault troubleshooting compendiumDiagnose and resolve errors in OpenSCAD, 3dMake, CMD, PowerShell, Git Bash, slicers, and printers
Student GlossaryTerms, definitions, and code examples across all curriculum systemsLook up any term encountered in lessons, with syntax examples for each shell
Teacher GlossaryPedagogical frameworks, instructional strategies, and assessment rubricsInstructors: curriculum design, scaffolding, computational thinking, and cross-curricular connections
Further Reading and ReferencesScholarly works, official documentation, industry resources, and community linksContinue learning; cite sources; find community support


Technical Reference and Troubleshooting Guide


PART I — SYSTEMS ARCHITECTURE

1.1 Digital Fabrication Pipeline

Source (.scad)
    ↓
OpenSCAD Engine
    ↓
STL (Mesh Geometry)
    ↓
Slicer
    ↓
G-code
    ↓
FDM Printer Firmware
    ↓
Physical Object

Automation Overlay:

CLI -> Script -> Build Directory -> Version Control -> Reproducible Artifact

PART II — OPENSCAD PROFESSIONAL MODELING REFERENCE

2.1 Language Architecture

OpenSCAD is:

  • Declarative
  • CSG-based
  • Deterministic
  • Single-pass evaluation
  • Non-interactive

Implication: Models must be architected intentionally.


2.2 Advanced Geometry Techniques

2.2.1 Transform Stack Order

Transformations apply from inside outward.

translate([10,0,0])
    rotate([0,0,45])
        cube(10);

Order matters.


2.2.2 Hull()

Creates convex hull of objects.

hull() {
    translate([0,0,0]) sphere(5);
    translate([20,0,0]) sphere(5);
}

2.2.3 Minkowski()

Expands object by shape kernel.

minkowski() {
    cube([10,10,10]);
    sphere(1);
}

Warning: Computationally expensive.


2.2.4 Linear and Rotational Extrusion

linear_extrude(height=10)
    square(5);

rotate_extrude()
    translate([10,0,0])
        circle(5);

2.2.5 Projection

projection(cut=true)
    sphere(10);

2.3 CLI Operation of OpenSCAD

Render STL (All shells)

openscad -o output.stl input.scad

Specify Variables via CLI

openscad -D width=50 -o model.stl model.scad

PART III — 3DMAKE PROFESSIONAL USAGE

3.1 3dMake Overview

3dMake automates model generation and batch workflows.

Core capabilities:

  • Batch STL generation
  • File processing pipelines
  • Integration with OpenSCAD CLI
  • Script-driven builds

Repository: https://github.com/tdeck/3dmake


3.2 Example Automated Pipeline (PowerShell)

New-Item -ItemType Directory -Force build
openscad -D width=40 -o build/model.stl src/model.scad
if ($LASTEXITCODE -ne 0) { exit 1 }

3.3 Batch Processing (cmd.exe)

for %%f in (src\*.scad) do openscad -o build\%%~nf.stl %%f

3.4 Batch Processing (Git Bash)

for f in src/*.scad; do
  openscad -o build/$(basename "$f" .scad).stl "$f"
done

PART IV — WINDOWS COMMAND PROMPT (CMD.EXE) FULL REFERENCE

4.1 cmd Architecture

  • Text-based
  • Legacy DOS-compatible syntax
  • String-based (not object-based)

Executable:

C:\Windows\System32\cmd.exe

4.2 File System Operations

List Files

dir

Change Directory

cd builds

Create Directory

mkdir build

Remove Directory

rmdir /s /q build

4.3 Running Programs

openscad.exe -o model.stl model.scad

4.4 PATH Inspection

echo %PATH%

4.5 Temporary Environment Variables

set MYVAR=value

4.6 Exit Codes

echo %ERRORLEVEL%

Conditional:

if %ERRORLEVEL% NEQ 0 echo Build failed

4.7 Batch Files (.bat)

Example build.bat:

@echo off
mkdir build
openscad -o build\model.stl src\model.scad
if %ERRORLEVEL% NEQ 0 exit /b 1

PART V — POWERSHELL PROFESSIONAL REFERENCE

5.1 Architecture

  • Object-based pipeline
  • .NET-backed
  • Strong scripting support

5.2 Execution Policy

Get-ExecutionPolicy
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

5.3 Structured Error Handling

try {
    openscad -o model.stl model.scad
}
catch {
    Write-Host "Failure"
}

PART VI — GIT BASH (UNIX-LIKE SHELL)

6.1 POSIX-Compatible Commands

ls
pwd
mkdir
rm -rf build

6.2 Shell Variables

VAR=value
echo $VAR

PART VII — ADVANCED TROUBLESHOOTING COMPENDIUM


A. OpenSCAD Failures

A.1 Segmentation Fault

Cause:

  • Deep Minkowski
  • Memory exhaustion

Fix:

  • Reduce $fn
  • Simplify geometry

A.2 Empty STL Output

Cause:

  • Geometry evaluates to null

Diagnosis: Add temporary primitive to confirm render pipeline.


A.3 Boolean Artifacts

Cause:

  • Coplanar faces

Fix:

  • Add small offsets (0.01mm)

A.4 Syntax Errors

Missing Semicolons

Cause:

cube([10,10,10])  // Missing semicolon

Fix:

cube([10,10,10]);

Unmatched Brackets

Common errors:

  • { } curly brackets
  • [ ] square brackets
  • ( ) parentheses

Diagnosis: Check error line number in console.


Comment Syntax Errors

Invalid multiline comment:

/* Comment
// Still in comment
*/

Single-line comments use // Multiline comments use /* */


A.5 Logical Operator Errors

&& (AND) Usage

if (x > 5 && y < 10) {
    cube([10,10,10]);
}

|| (OR) Usage

if (x > 5 || y < 10) {
    cube([10,10,10]);
}

Missing parentheses can cause evaluation errors.


A.6 $fn Performance Issues

Cause:

  • Excessive fragment count

Example:

$fn = 500;  // Too high
sphere(5);

Fix:

$fn = 50;   // Sufficient for most cases
sphere(5);

B. 3dMake Failures

B.1 Command Not Found

Verify:

where openscad

Or check 3dm:

where 3dm

B.2 Silent Failure

Check exit code:

echo %ERRORLEVEL%

B.3 3dm build Failures

Common causes:

  • Source file not found
  • Syntax errors in .scad
  • OpenSCAD not in PATH

Diagnosis:

3dm build --verbose

B.4 3dm info Not Working

Requirements:

  • Valid STL file
  • Network connection (for AI service)

Check:

3dm info

If info works but describe doesn’t, check network.


C. Command Line Lesson Specific Failures

C.1 “Access is denied”

Cause:

  • Insufficient privileges

Fix: Run as Administrator.


C.2 Incorrect Variable Expansion in Loop

In batch files use:

%%f

In interactive shell use:

%f

D. PowerShell-Specific Failures

D.1 Script Not Running

Fix:

Set-ExecutionPolicy RemoteSigned

D.2 Command Returns But File Not Created

Check:

Test-Path build\model.stl

E. Git Bash Issues

E.1 Windows Path Confusion

Use forward slashes:

openscad -o build/model.stl src/model.scad

F. 3D Printing Mechanical Failures

F.1 Warping

Solutions:

  • Increase bed temp
  • Use enclosure
  • Add brim

F.2 Under-Extrusion

Cause:

  • Clogged nozzle
  • Incorrect flow rate

F.3 Dimensional Error

Test with calibration cube.


G. Performance Diagnostics

G.1 Slow Render

Reduce:

  • $fn
  • Minkowski usage
  • Nested difference()

G.2 High CPU Usage

Expected during full render.


G.3 For Loop Performance

Inefficient:

for (i = [0:1000]) {
    translate([i, 0, 0])
        minkowski() { ... }  // Very slow
}

Better:

for (i = [0:100]) {  // Reduce iterations
    translate([i, 0, 0])
        hull() { ... }   // Faster than minkowski
}

G.4 Hull vs Minkowski Performance

  • hull() — Fast for convex shapes
  • minkowski() — Slow but precise

Use hull() when possible.


H. SYSTEM DIAGNOSTIC CHECKLIST

  1. Is OpenSCAD in PATH?
  2. Does CLI produce STL?
  3. Is STL manifold?
  4. Does slicer preview correctly?
  5. Is G-code generated?
  6. Does printer firmware accept G-code?
  7. Is first layer adhering?
  8. Are dimensions within tolerance?
  9. Are all brackets matched?
  10. Are comments properly closed?
  11. Is $fn set reasonably?
  12. Are transform operations in correct order?

J. EDITOR AND IDE TROUBLESHOOTING

J.1 VS Code OpenSCAD Extension Issues

Symptom:

  • No syntax highlighting

Fix:

  1. Install “OpenSCAD” extension
  2. Restart VS Code
  3. Check file extension is .scad

J.2 Notepad++ Syntax Highlighting

Setup:

  1. Settings > Style Configurator
  2. Select Language: C or C++
  3. Apply to .scad files

J.3 Indentation Issues

Mixed tabs/spaces:

Fix:

Convert tabs to spaces
Set indent to 4 spaces

J.4 Screen Reader + Editor Issues

NVDA with VS Code

Settings:

  • Enable “Editor > Accessibility: Support”
  • Set “Editor > Render Whitespace”: “all”

Indent Announcement

NVDA:

  • Document Formatting > Report line indentation

JAWS:

  • Settings Center > Reading > Report Indentation

K. SLICER-SPECIFIC TROUBLESHOOTING

K.1 PrusaSlicer Import Failures

Symptom:

  • STL won’t load

Causes:

  • Non-manifold geometry
  • File corruption
  • Incorrect file path

Fix:

openscad -o model.stl model.scad --check

K.2 Cura Slicing Errors

Common:

  • Model outside build volume
  • Unsupported overhangs

Fix:

  • Scale model down
  • Enable supports

K.3 Bambu Studio Issues

Plate adhesion:

  • Clean build plate
  • Increase bed temperature
  • Add brim/raft

L. MATERIAL-SPECIFIC FAILURES

L.1 PLA Printing Issues

Stringing

Fix:

  • Enable retraction
  • Lower temperature by 5-10°C

Warping

  • Rare with PLA
  • Add brim if occurs

L.2 PETG Challenges

Stringing

Common with PETG.

Fix:

  • Increase retraction distance
  • Lower temperature

Bed Adhesion

Too good — may damage bed.

Use:

  • Glue stick as release agent

L.3 TPU (Flexible) Problems

Under-extrusion

Cause:

  • Too fast print speed

Fix:

  • Reduce to 20-30 mm/s

Stringing

Minimal retraction:

  • Set to 1-2mm only

L.4 ABS Warping

Major challenge.

Required:

  • Heated enclosure
  • 100°C+ bed temp
  • Large brim

M. MEASUREMENT AND QA FAILURES

M.1 Caliper Measurement Errors

Over-tightening

Cause:

  • Pressing too hard

Result:

  • Part deforms
  • Inaccurate reading

Fix:

  • Use gentle pressure

M.2 Tolerance Stack-up Issues

Multiple parts don’t fit.

Analysis:

Part A: +0.15mm error
Part B: +0.12mm error
Total: +0.27mm

Fix:

  • Adjust design tolerances
  • Print test pieces first

M.3 Dimensional Accuracy Check

Print calibration cube:

cube([20,20,20]);

Measure all dimensions. Expected: 20.00 ± 0.2mm


I. FULL BUILD VALIDATION SCRIPT (CMD)

@echo off
echo Validating environment...
where openscad >nul 2>nul
if %ERRORLEVEL% NEQ 0 (
    echo OpenSCAD not found.
    exit /b 1
)

mkdir build
openscad -o build\model.stl src\model.scad
if %ERRORLEVEL% NEQ 0 (
    echo Build failed.
    exit /b 1
)

echo Build succeeded.

N. TEXT EMBOSSING TROUBLESHOOTING

N.1 Font Not Found

Symptom:

WARNING: No match for font family

Cause:

  • Font name incorrect
  • Font not installed

Fix:

Windows (PowerShell):

[System.Drawing.Text.InstalledFontCollection]::new().Families | Select-Object Name

Linux:

fc-list | grep -i "font name"

N.2 Text Not Visible

Cause:

  • Forgot linear_extrude()

Wrong:

text("HELLO");

Correct:

linear_extrude(height=2)
    text("HELLO");

N.3 Text Size Too Large/Small

Cause:

  • Size parameter is cap height in mm

Fix:

text("HELLO", size=8);  // 8mm tall letters

O. TRANSFORM OPERATION ERRORS

O.1 Transform Order Confusion

Transforms apply inside-out.

Example:

translate([10,0,0])    // Applied SECOND
    rotate([0,0,45])    // Applied FIRST
        cube([10,10,10]);

Order matters!


O.2 Rotate Angles Wrong

Angles in degrees, not radians.

rotate([0, 0, 45]);  // 45 degrees

O.3 Scale Issues

scale([2, 1, 1])  // 2x wider only
    cube([10,10,10]);

Result: 20×10×10 cube


O.4 Mirror Confusion

Mirror plane:

mirror([1, 0, 0])  // Mirror across YZ plane
    cube([10,10,10]);

P. IMPORT AND EXPORT ERRORS

P.1 Import STL Failed

Cause:

  • File path incorrect
  • File corrupted

Fix:

import("path/to/file.stl");

Use forward slashes even on Windows.


P.2 Export Failed

Check:

  1. Write permissions
  2. Sufficient disk space
  3. Valid file path

Q. RANDOMIZATION ISSUES

Q.1 rands() Not Random

Cause:

  • Same seed produces same output
vals = rands(0, 100, 10, 42);  // Seed = 42

Change seed for different results.


Q.2 Random Position Overlap

Objects placed randomly may overlap.

Need collision detection logic.



Student Glossary — OpenSCAD • 3dMake • 3D Printing • PowerShell • Command Prompt • Git Bash


OpenSCAD • 3dMake • 3D Printing • PowerShell • Command Prompt • Git Bash

This glossary provides:

  • Formal definitions
  • Operational context
  • Cross-system distinctions
  • CLI examples
  • Practical implications in 3D printing workflows

SECTION I — Additive Manufacturing & Fabrication

Additive Manufacturing

A manufacturing methodology in which objects are fabricated layer-by-layer from digital models.
In desktop contexts, this typically refers to FDM (Fused Deposition Modeling).

Technical Characteristics

  • Layer-based deposition
  • Toolpath-generated geometry
  • STL-to-G-code workflow
  • Thermoplastic extrusion (in FDM)

Workflow Position

OpenSCAD -> STL -> Slicer -> G-code -> Printer -> Physical object


FDM (Fused Deposition Modeling)

A thermoplastic extrusion process in which filament is melted and deposited in sequential layers.

Critical Variables

  • Nozzle temperature
  • Bed temperature
  • Layer height
  • Print speed
  • Cooling rate

Layer Height

The vertical thickness of each printed layer.

  • Smaller values increase surface fidelity.
  • Larger values increase speed.

Example:

  • 0.2 mm = standard
  • 0.1 mm = high resolution

Infill

Internal structural lattice inside a model.

Typical values:

  • 10–20% for visual models
  • 40%+ for structural parts

Material Properties

PLA (Polylactic Acid)

  • Easy to print
  • Low warping
  • Biodegradable
  • Not heat-resistant

PETG

  • Stronger than PLA
  • Chemical resistant
  • Slight flexibility

TPU (Thermoplastic Polyurethane)

  • Flexible
  • Rubber-like
  • Requires slow printing

ABS (Acrylonitrile Butadiene Styrene)

  • Strong and durable
  • Higher temperature
  • Requires enclosure
  • Prone to warping

Tolerance

Intentional dimensional offset to ensure mechanical fit.

Example: A 10mm peg may require a 10.2mm hole for clearance.


Manifold (Watertight Model)

A printable model with:

  • No self-intersections
  • No zero-thickness faces
  • No holes in mesh

Non-manifold geometry causes slicer failure.


SECTION II — OpenSCAD (Parametric Modeling)

OpenSCAD

A script-based solid modeling system using Constructive Solid Geometry (CSG).

Official site: https://openscad.org


Constructive Solid Geometry (CSG)

Modeling technique combining primitives using Boolean operations.


Primitive

Basic geometric object.

Examples:

cube([10,10,10]);
sphere(5);
cylinder(h=20, d=10);

Cone

A tapered cylinder created using different top and bottom diameters.

cylinder(h=20, d1=10, d2=0);

2D Shapes

Flat geometry that can be extruded to 3D.

Examples:

square([10,10]);
circle(5);
polygon([[0,0], [10,0], [5,10]]);

Polygon

Custom 2D shape defined by vertices.

polygon(points=[[0,0], [10,0], [10,10], [0,10]]);

Text Commands

Create text geometry for embossing or debossing.

linear_extrude(height=2)
    text("HELLO", size=10, font="Liberation Sans");

Boolean Operations

union()

Combines shapes.

union() {
    cube([10,10,10]);
    sphere(6);
}

difference()

Subtracts shapes.

difference() {
    cube([20,20,20]);
    cylinder(h=25, d=5);
}

intersection()

Keeps overlapping geometry.

intersection() {
    sphere(10);
    cube([15,15,15], center=true);
}

Transform Operations

Translate

Move geometry in 3D space.

translate([10, 20, 30])
    cube([10,10,10]);

Rotate

Rotate geometry around axes.

rotate([0, 0, 45])
    cube([10,10,10]);

Scale

Resize geometry by multiplier.

scale([2, 1, 1])
    cube([10,10,10]);

Mirror

Flip geometry across a plane.

mirror([1, 0, 0])
    cube([10,10,10]);

Advanced Operations

Hull

Creates convex hull of children objects.

hull() {
    sphere(5);
    translate([20,0,0]) sphere(5);
}

Minkowski Sum

Expands geometry by rolling one shape around another.

minkowski() {
    cube([10,10,10]);
    sphere(2, $fn=12);
}

Warning: Computationally expensive.


Linear Extrude

Extends 2D shapes into 3D.

linear_extrude(height=10)
    square([10,10]);

Offset

Expands or contracts 2D shapes.

offset(r=2)
    square([10,10]);

Variable

A named parameter used to control geometry.

width = 30;
cube([width,10,5]);

Parametric Design

Geometry controlled by variables.

Advantages:

  • Rapid iteration
  • Reusability
  • Scalable models

Module

Reusable geometry block.

module peg(d, h) {
    cylinder(d=d, h=h);
}

peg(5, 20);

Control Structures

For Loop

Repeat operations.

for (i = [0:5]) {
    translate([i*15, 0, 0])
        cube([10,10,10]);
}

If Statement

Conditional execution.

if (width > 20) {
    cube([width, 10, 10]);
}

Else and ElseIf

Extended conditionals.

if (width > 20) {
    cube([width, 10, 10]);
} else if (width > 10) {
    cylinder(h=10, d=width);
} else {
    sphere(width/2);
}

Echo Function

Print debug information to console.

width = 30;
echo("Width is:", width);

Random Numbers

Generate random values.

rands(min, max, count, seed);

// Example:
positions = rands(0, 100, 5);

Import

Load external STL or other files.

import("model.stl");

$fn (Fragment Number)

Controls circular resolution.

$fn = 100;
sphere(10);

Higher values increase smoothness and render time.


# (Hash Mark - Debug Modifier)

Highlights geometry in transparent red during preview.

#cube([10,10,10]);

Used for debugging geometry positions.


Comments

Non-executable text for documentation.

Single-line Comments

// This is a comment
cube([10,10,10]);

Multiline Comments

/*
  This is a
  multiline comment
*/
cube([10,10,10]);

Logical Operators

&& (And)

Logical AND operator.

if (x > 5 && y < 10) {
    cube([10,10,10]);
}

|| (Or)

Logical OR operator.

if (x > 5 || y < 10) {
    cube([10,10,10]);
}

Brackets and Delimiters

[ ] (Square Brackets)

Used for vectors and arrays.

position = [10, 20, 30];
cube([10,10,10]);

{ } (Curly Brackets)

Define code blocks.

if (x > 5) {
    cube([10,10,10]);
}

< > (Angle Brackets)

Used in some operations and comparisons.

if (x < 10 && y > 5) { }

Preview vs Render

  • F5 = Preview (OpenGL approximation)
  • F6 = Render (full CSG evaluation)

CLI equivalent:

openscad -o model.stl model.scad

SECTION III — 3dMake (Automation Tool)

3dMake

A command-line tool for automating 3D model generation and processing.

Repository: https://github.com/tdeck/3dmake


3dm build

Command to generate STL from OpenSCAD source.

3dm build

Outputs to build/ directory.


3dm info

AI-powered geometric description for non-visual validation.

3dm info --view front

Headless Rendering

Running OpenSCAD without GUI.

openscad -o output.stl input.scad

Automated Build Pipeline

Example PowerShell pipeline:

openscad -o model.stl model.scad

Example Bash:

openscad -o model.stl model.scad

SECTION IV — Command-Line Systems

CLI (Command-Line Interface)

A text-based interface for interacting with the operating system.


Shell

A program that interprets commands.

Examples:

  • PowerShell
  • Command Prompt
  • Git Bash

PowerShell

Object-oriented Windows shell.

List Files

Get-ChildItem

Change Directory

Set-Location Documents

Run Script

.\build.ps1

Check Exit Code

$LASTEXITCODE

Command Prompt (cmd.exe)

Traditional Windows shell.

List Files

dir

Change Directory

cd Documents

Run Program

openscad.exe -o model.stl model.scad

Check Exit Code

echo %ERRORLEVEL%

Git Bash

Unix-like shell for Windows.

List Files

ls

Change Directory

cd Documents

Make Directory

mkdir builds

Working Directory

The directory in which commands execute.

pwd
Get-Location

PATH (Environment Variable)

Tells system where executables are located.

View PATH (PowerShell)

$env:PATH

View PATH (cmd)

echo %PATH%

Environment Variable

A system-level configuration variable.

Set Temporarily (PowerShell)

$env:TESTVAR="hello"

Set Temporarily (cmd)

set TESTVAR=hello

Exit Code

Numeric status returned by command.

  • 0 = Success
  • Non-zero = Error

Example:

if ($LASTEXITCODE -ne 0) { Write-Host "Build Failed" }
if [ $? -ne 0 ]; then echo "Build Failed"; fi

Pipe

Pass output from one command to another.

Get-ChildItem | Select-String ".scad"
ls | grep ".scad"

SECTION V — Git & Version Control

Git

Distributed version control system.


Repository

Tracked project folder.

git init

Commit

Snapshot of changes.

git add .
git commit -m "Initial model"

Branch

Parallel development path.

git branch feature-peg
git checkout feature-peg

Clone

Download remote repository.

git clone https://github.com/user/project.git

Status

Check changes.

git status

SECTION VI — File Formats

STL

Triangle mesh file used in 3D printing.

Generated by:

openscad -o model.stl model.scad

Slicer Software

Converts STL to G-code.

PrusaSlicer

Open-source slicer with advanced features.

Cura

User-friendly slicer by Ultimaker.

Bambu Studio

Slicer for Bambu Lab printers.


G-code

Machine instructions generated by slicer.

Example fragment:

G1 X10 Y10 Z0.2 F1500

SECTION VII — Automation Concepts

Script

File containing executable instructions.

Examples:

  • .ps1
  • .sh
  • .scad

Debugging

Process of finding and fixing errors in code.

Techniques:

  • Use echo() statements
  • Use # modifier to highlight geometry
  • Test modules independently
  • Check console for warnings

Reproducibility

Ability to regenerate identical outputs from identical inputs.


Automation

Using scripts instead of manual steps.

Example build script (PowerShell):

openscad -o build/model.stl src/model.scad

SECTION VIII — Accessibility & Documentation

Markdown

Lightweight markup language.

Example:

# Heading
- Bullet

Semantic Structure

Proper heading hierarchy:

# Title
## Section
### Subsection

Important for screen readers.


Editor Setup

VS Code

Recommended extensions:

  • OpenSCAD Language Support
  • Bracket Pair Colorizer

Notepad++

Lightweight editor with syntax highlighting.

Configure:

  • Settings > Preferences > Language
  • Select OpenSCAD or C-style syntax

Indentation

Proper code formatting for readability.

module example() {
    if (condition) {
        cube([10,10,10]);
    }
}

Use consistent spacing (2 or 4 spaces per level).


Screen Reader

Software that reads text aloud.

Examples:

  • NVDA
  • JAWS
  • Orca
  • VoiceOver

SECTION IX — Mechanical Design Concepts

Clearance Fit

Loose fit allowing movement.

Press Fit

Tight fit requiring force.

Overhang

Unsupported geometry exceeding safe angle (≈45° for FDM).


Tolerance

Intentional dimensional offset for mechanical fit.

Example:

  • Designed hole: 10.2mm
  • Designed peg: 10.0mm
  • Clearance: 0.2mm

Calipers

Precision measurement tool for verifying printed dimensions.

Types:

  • Digital calipers (recommended)
  • Vernier calipers

Accuracy: ±0.01mm typical


SECTION X — Advanced Workflow Concepts

Headless CI Build

Automated rendering using scripts or CI tools.

openscad -o output.stl model.scad

Deterministic Modeling

Same input -> same output every time.

OpenSCAD is deterministic.


Dependency

External program required for workflow.

Example:

  • OpenSCAD must be in PATH.


Teacher Glossary — Pedagogical Concepts for 3D Design and Computational Thinking Instruction


Pedagogical Concepts for 3D Design & Computational Thinking Instruction

This glossary provides instructors with:

  • Pedagogical frameworks
  • Teaching strategies
  • Assessment concepts
  • Accessibility guidance
  • Curriculum design principles

SECTION I — Computational Thinking Framework

Computational Thinking

Problem-solving approach using concepts fundamental to computer science.

Core pillars:

  • Decomposition — Breaking problems into smaller parts
  • Pattern Recognition — Identifying similarities
  • Abstraction — Focusing on relevant details
  • Algorithms — Creating step-by-step solutions

Application in OpenSCAD: Students decompose complex models into primitive shapes, recognize geometric patterns, abstract parameters, and write algorithmic module definitions.


Decomposition

Breaking a complex problem into manageable sub-problems.

In 3D Design Context

Example: A phone stand is decomposed into:

  1. Base plate
  2. Support angle
  3. Lip to hold phone
  4. Optional cable slot

Each component becomes a separate module.


Abstraction

Removing unnecessary details to focus on essential features.

In Parametric Design

module bolt(diameter, length) {
    // Abstract "bolt" concept
    // Hide implementation details
}

Students learn to identify which details matter and which can be parameterized.


Pattern Recognition

Identifying repeating structures or concepts.

Examples in OpenSCAD

  • Repeated geometric elements (array of holes)
  • Similar transformation sequences
  • Common parameter relationships

Algorithms

Step-by-step procedures for solving problems.

In Code

// Algorithm for creating gear teeth
for (i = [0:teeth-1]) {
    rotate([0, 0, i * 360/teeth])
        translate([radius, 0, 0])
            tooth_profile();
}

SECTION II — Instructional Design Strategies

Walking Skeleton Approach

Agile development practice: build minimal working version first, then iterate.

In 3D Design Curriculum

  1. Create basic cube
  2. Add one parameter
  3. Add one transformation
  4. Build and verify
  5. Repeat

Prevents overwhelming students with complexity.


Design Cycle

Iterative process:

Define -> Ideate -> Prototype -> Test -> Refine -> Repeat

In 3dMake Context

Edit .scad -> 3dm build -> 3dm info -> Measure print -> Adjust parameters

Scaffolding

Temporary support structures that enable learning.

Examples:

  • Starter code templates
  • Pre-defined modules
  • Graduated exercises
  • Checklists

Remove scaffolding as competency increases.


Physical Computing

Learning that connects digital design to physical artifacts.

3D printing provides immediate tangible feedback:

  • Code -> STL -> Physical object
  • Reinforces cause-and-effect
  • Engages kinesthetic learners

Stakeholder-Centric Design

Designing with end-user needs in focus.

Teaching Application

Have students:

  1. Interview stakeholders
  2. Define requirements
  3. Create design constraints
  4. Iterate based on feedback

Example: Design assistive device for specific user needs.


SECTION III — Assessment & Validation

Code Review Criteria

Assess student code on:

  1. Functionality — Does it work?
  2. Parametrization — Are values abstracted?
  3. Documentation — Are comments clear?
  4. Modularity — Is code reusable?
  5. Efficiency — Is approach optimal?

Quality Assurance

Systematic verification process.

For 3D Prints

  • Measure with calipers
  • Compare to specification
  • Document deviations
  • Adjust parameters
  • Retest

Teaches scientific method and iterative refinement.


Safety Protocols

3D Printing Safety

Required instruction:

  • Ventilation requirements
  • Hot surface warnings
  • Electrical safety
  • Material handling (MSDS)
  • Emergency shutdown procedures

SECTION IV — Accessibility & Universal Design

Screen Reader Accessibility Guide

Ensure all students can access curriculum.

Key Principles

  1. Semantic HTML/Markdown — Proper heading structure
  2. Alt text for images — Describe geometric concepts
  3. CLI-first workflows — Reduce GUI dependence
  4. Descriptive output3dm info provides text descriptions

Braille Display Setup

For students using refreshable braille displays:

  1. Ensure code editors support screen readers
  2. Use semantic indentation (not tabs)
  3. Provide geometric descriptions in text
  4. Test commands with NVDA/JAWS

Indent Announcement Configuration

Configure screen readers to verbalize indentation level.

NVDA

Settings > Document Formatting > Report line indentation

JAWS

Settings Center > Reading > Report Indentation

Critical for understanding OpenSCAD block structure.


Non-Visual Toolchain Introduction

Guide blind/low-vision students through:

  1. CLI navigation (pwd, ls, cd)
  2. Text editor setup (VS Code with extensions)
  3. 3dm build command
  4. 3dm info for validation
  5. Caliper measurement techniques (tactile)

Editor Setup for Accessibility

VS Code

Recommended extensions:

  • Screen Reader Optimized
  • Bracket Pair Colorizer (announces nesting)
  • OpenSCAD Language Support

Notepad++

Lightweight alternative:

  • Configure indentation announcement
  • Enable line number reading
  • Set up hotkeys for navigation

SECTION V — Technical Teaching Concepts

Parametric Architecture

Design philosophy where dimensions are variables, not fixed values.

Why Teach This

  • Promotes computational thinking
  • Enables design reuse
  • Teaches variable scope
  • Reinforces algebra concepts

Geometric Primitives

Basic 3D shapes that combine to form complex objects.

Teaching Sequence

  1. Cube
  2. Sphere
  3. Cylinder (including cones)
  4. Boolean operations
  5. Transformations
  6. Compound models

Tolerance Management

Critical mechanical engineering concept.

Teaching Approach

  1. Print test parts
  2. Measure with calipers
  3. Calculate error
  4. Adjust tolerance parameters
  5. Reprint and verify

Teaches:

  • Precision vs accuracy
  • Measurement techniques
  • Iterative refinement

Interlocking Features

Mechanical joints and assemblies.

Examples:

  • Snap fits
  • Press fits
  • Sliding joints
  • Threaded connections

Requires understanding of:

  • Clearance tolerances
  • Material properties
  • Force analysis

SECTION VI — Curriculum Design Elements

Design Mode vs Print Mode

OpenSCAD workflows:

  • Design Mode (F5) — Fast preview
  • Print Mode (F6) — Full render for STL export

Teach distinction early to avoid confusion.


Editor Window vs Preview Window

OpenSCAD interface:

  • Left: Code editor
  • Right: 3D preview

Non-visual students use editor + CLI tools instead of preview.


File Format Progression

Teach file types in order:

  1. .scad — Source code
  2. .stl — 3D mesh
  3. .gcode — Machine instructions

Each represents different abstraction level.


Debugging Strategies

Systematic approaches to finding errors.

For Students

  1. Read error messages carefully
  2. Use echo() to print values
  3. Test modules independently
  4. Use # modifier to highlight geometry
  5. Simplify to minimal failing case

SECTION VII — Cross-Curricular Connections

Mathematics Integration

3D design reinforces:

  • Coordinate geometry (X, Y, Z axes)
  • Trigonometry (rotation angles)
  • Algebra (parametric equations)
  • Measurement & units

Physics Applications

  • Center of mass calculations
  • Material properties (stress, strain)
  • Thermal expansion
  • Friction coefficients

Engineering Design Process

Professional workflow:

  1. Define problem
  2. Research requirements
  3. Brainstorm solutions
  4. Build prototype
  5. Test and evaluate
  6. Refine design

3D printing makes this tangible.


SECTION VIII — Slicing & Print Management

Slicing Guides for Instruction

PrusaSlicer

Recommended teaching slicer:

  • Visual layer preview
  • Built-in supports
  • Print time estimates

Cura

Alternative:

  • Simpler interface
  • Good for beginners

Bambu Studio

For Bambu Lab printers:

  • Automated features
  • Multi-color support

Material Selection Pedagogy

PLA

Start here:

  • Easiest to print
  • Lowest temperature
  • Minimal warping

PETG

Intermediate:

  • Stronger
  • More forgiving than ABS

TPU

Advanced:

  • Flexible prints
  • Requires special techniques

ABS

Advanced:

  • Professional applications
  • Requires enclosure
  • Warping challenges teach troubleshooting

SECTION IX — Language & Syntax Teaching

Code Statement

Single executable instruction.

cube([10,10,10]);  // One statement

Comments as Documentation

Teach commenting best practices:

  1. Explain why, not what
  2. Document parameters
  3. Include units
  4. Note constraints

Arithmetic in Code

Reinforce math concepts:

width = 10;
spacing = width * 1.5;  // Arithmetic

SECTION X — Assessment Rubrics

Parametric Design Rubric

CriterionNoviceDevelopingProficientAdvanced
ParameterizationHard-coded valuesSome parametersMost values parameterizedFull parametric architecture
DocumentationNo commentsMinimal commentsClear parameter docsComprehensive documentation
ModularityNo modulesBasic modulesReusable modulesLibrary-quality modules
FunctionalityDoesn’t buildBuilds with errorsMeets requirementsExceeds requirements

Manufacturing Readiness Rubric

CriterionAssessment
Manifold geometryPass/Fail
Tolerance specifiedPass/Fail
Documentation completePass/Fail
Quality measurements recordedPass/Fail

SECTION XI — Troubleshooting Pedagogy

Teaching Debugging

Framework:

  1. Reproduce — Can you make it fail consistently?
  2. Isolate — What’s the minimal failing case?
  3. Hypothesize — What might cause this?
  4. Test — How can you verify?
  5. Document — What did you learn?

Common Student Errors

Syntax Errors

  • Missing semicolons
  • Unmatched brackets
  • Typos in keywords

Logical Errors

  • Wrong parameter order
  • Incorrect units
  • Transform order confusion

Practical Errors

  • Model too large for print bed
  • Overhangs without support
  • Wall thickness too thin

SECTION XII — Project-Based Learning

Scaffolded Project Sequence

  1. Week 1-2: Primitives and transformations
  2. Week 3-4: Modules and parameters
  3. Week 5-6: Boolean operations
  4. Week 7-8: Multi-part assemblies
  5. Week 9-10: Student-designed project

Portfolio Assessment

Students maintain portfolio showing:

  • Design evolution
  • Failed prototypes (with analysis)
  • Final products
  • Measurements and QA data
  • Reflection on process


Further Reading and References


Peer-Reviewed and Scholarly Works

Gonzalez Avila, J. F., Pietrzak, T., Girouard, A., & Casiez, G. (2024). Understanding the challenges of OpenSCAD users for 3D printing. In Proceedings of the CHI Conference on Human Factors in Computing Systems (CHI ’24) (Article 351, pp. 1–20). Association for Computing Machinery. https://doi.org/10.1145/3613904.3642566 :contentReference[oaicite:0]{index=0}

Li, G. (2024). Chinese dragon modeling based on OpenSCAD. Applied and Computational Engineering, 67, 1–12. https://doi.org/10.54254/2755-2721/67/20240585 :contentReference[oaicite:1]{index=1}

Kwon, N., Sun, T., Gao, Y., Zhao, L., Wang, X., Kim, J., & Hong, S. R. (2024). 3DPFIX: Improving remote novices’ 3D printing troubleshooting through human-AI collaboration. arXiv. https://doi.org/10.48550/arXiv.2401.15877 :contentReference[oaicite:2]{index=2}

Government & Standards

Centers for Disease Control and Prevention, National Institute for Occupational Safety and Health. (2020, May 14). Health and safety considerations for 3D printing. https://blogs.cdc.gov/niosh-science-blog/2020/05/14/3d-printing/

Centers for Disease Control and Prevention, National Institute for Occupational Safety and Health. (2024). Approaches to safe 3D printing. https://www.cdc.gov/niosh/blogs/2024/safe-3d-printing.html

National Institute of Standards and Technology. (2023). Artificial Intelligence Risk Management Framework (AI RMF 1.0). https://www.nist.gov/system/files/documents/2023/01/26/AI%20RMF%201.0.pdf

Occupational Safety and Health Administration. (n.d.). Hierarchy of controls. https://www.osha.gov/hierarchy-of-controls

Washington State Department of Health. (n.d.). 3D printers in schools. https://doh.wa.gov/community-and-environment/schools/3d-printers

Industry & Commercial Documentation

All3DP. (n.d.). 3D printer filament types explained. https://all3dp.com/1/3d-printer-filament-types-3d-printing-3d-filament/

All3DP. (n.d.). FDM 3D printing tolerances. https://all3dp.com/2/fdm-3d-printing-tolerances/

Anycubic. (n.d.). Anycubic. https://www.anycubic.com/

Autodesk. (n.d.). Fusion 360. https://www.autodesk.com/products/fusion-360

Bambu Lab. (n.d.). Downloads. https://bambulab.com/en/download

Bambu Lab. (n.d.). Bambu Studio. https://bambulab.com/en/download/studio

Bambu Lab Wiki. (n.d.). Bambu Lab Wiki. https://wiki.bambulab.com

Hubs. (n.d.). What is FDM 3D printing? https://www.hubs.com/knowledge-base/what-is-fdm-3d-printing/

IDEA Maker (Raise3D). (n.d.). ideaMaker. https://www.raise3d.com/ideamaker

MatterHackers. (n.d.). 3D printer filament comparison. https://www.matterhackers.com/3d-printer-filament-compare

Prusa Research. (n.d.). PrusaSlicer 4.2.4. https://www.prusa3d.com/page/prusaslicer424/

Prusa Research. (n.d.). PrusaSlicer 4.1.0. https://www.prusa3d.com/page/prusaslicer_410/

Prusa Research. (n.d.). Support. https://www.prusa3d.com/support/

Stratasys. (n.d.). Stratasys. https://stratasys.com/

UL Research Institutes. (n.d.). 3D printing emissions study. https://www.ul.com/news/ul-research-institutes-releases-3d-printing-emissions-study

Ultimaker. (n.d.). Ultimaker Cura. https://ultimaker.com/software/ultimaker-cura

ZenML. (n.d.). LLM-powered 3D model generation for 3D printing. https://www.zenml.io/llmops-database/llm-powered-3d-model-generation-for-3d-printing

Open-Source Software & Technical Documentation

Anthropic. (n.d.). Prompt engineering overview. https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview

Apache Software Foundation. (2004). Apache License, Version 2.0. https://www.apache.org/licenses/LICENSE-2.0

BelfrySCAD. (n.d.). BOSL2. https://github.com/BelfrySCAD/BOSL2

Deck, T. (2025). 3DMake repository. https://github.com/tdeck/3dmake

Free Software Foundation. (n.d.). GNU Bash manual. https://www.gnu.org/software/bash/manual/

Free Software Foundation. (n.d.). GNU Coreutils manual. https://www.gnu.org/software/coreutils/manual/

Free Software Foundation. (n.d.). GNU Grep manual. https://www.gnu.org/software/grep/manual/grep.html

Git SCM. (n.d.). Git documentation. https://git-scm.com/docs

Google Cloud. (2025). Get started with Gemini models. https://docs.cloud.google.com/vertex-ai/generative-ai/docs/start/get-started-with-gemini-3

Microsoft. (n.d.). PowerShell documentation. https://learn.microsoft.com/powershell/

Microsoft. (n.d.). Windows commands documentation. https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/

OpenSCAD. (n.d.). OpenSCAD documentation. https://openscad.org/documentation.html

OpenSCAD User Manual Contributors. (n.d.). OpenSCAD User Manual. https://en.wikibooks.org/wiki/OpenSCAD_User_Manual

Programming with OpenSCAD. (n.d.). Programming with OpenSCAD. https://programmingwithopenscad.github.io/

Rust Project Developers. (n.d.). mdBook. https://rust-lang.github.io/mdBook/

SuperSlicer. (n.d.). SuperSlicer repository. https://github.com/supermerill/SuperSlicer

The Linux Documentation Project. (n.d.). Bash Beginner’s Guide. https://tldp.org/LDP/Bash-Beginners-Guide/html/

Educational & Community Resources

A11Y-101. (n.d.). Inclusive documentation design. https://www.a11y-101.com/design/inclusive-documentation

Class Central. (n.d.). OpenSCAD courses. https://www.classcentral.com/subject/openscad

Khan Academy. (n.d.). Algorithms. https://www.khanacademy.org/computing/computer-science/algorithms

Salt Lake City Public Library. (n.d.). Creative Lab. https://services.slcpl.org/creativelab

Salt Lake County Library. (n.d.). Create spaces. https://www.slcolibrary.org/what-we-have/create

University of Utah. (n.d.). ProtoSpace. https://lib.utah.edu/protospace.php

Accessibility & Assistive Tech

Freedom Scientific. (n.d.). JAWS screen reader. https://www.freedomscientific.com/products/software/jaws/

Microsoft. (n.d.). Narrator guide. https://support.microsoft.com/narrator

NV Access. (n.d.). NVDA screen reader. https://www.nvaccess.org/

Your Dolphin. (n.d.). SuperNova. https://yourdolphin.com/supernova/

Community & Media

Discord. (n.d.). 3D printing community server. https://discord.gg/F2Nx2VxTB7

Reddit. (n.d.). r/3Dprinting subreddit. https://www.reddit.com/r/3Dprinting/

Reddit. (n.d.). r/OpenSCAD subreddit. https://www.reddit.com/r/openscad/

YouTube. (n.d.). Luke’s Lab channel. https://www.youtube.com/@LukesBlab

YouTube. (n.d.). Teaching Tech channel. https://www.youtube.com/@TeachingTech

Contributors to this Curriculum

Michael Ryan Hunsaker, M.Ed., Ph.D. (he/him)

About Dr. Hunsaker

Michael Ryan Hunsaker holds a Ph.D. in neuroscience (behavioral/translational neuroscience focus) from UC Davis and a Master’s degree in Special Education from the University of Utah with a credential to teach blind and visually impaired students. His career uniquely bridges scientific research, clinical experience, and classroom practice-positioning him to design accessible educational materials grounded in both neuroscience and practical pedagogy.

Research & Clinical Background

Following his doctoral work at UC Davis (2012), Dr. Hunsaker completed postdoctoral research in primate neural development at the UC Davis MIND Institute, where he developed sophisticated research methods to evaluate developmental disorders. During this period, he gained extensive clinical experience working directly with children and adults across a broad spectrum of diagnoses, including autism spectrum disorder, cerebral palsy, genetic conditions (fragile X syndrome, Williams syndrome, 22q11.2DS, Down syndrome), ADHD, and Tourette’s syndrome. This diverse exposure to different neurological profiles taught him a crucial lesson: each learner’s disability uniquely shapes their cognitive strengths, learning preferences, and educational needs.

Transition to Education

In 2013, recognizing the gap between academic research and classroom reality, Dr. Hunsaker made a deliberate career shift to direct education. Rather than pursue traditional academic pathways, he committed to applying his scientific training to help students in real classroom environments. As a special education teacher, he focused on understanding the individual relationship between disability and learning-developing instructional approaches that enable students to access their full potential rather than working around perceived limitations.

Expertise in Accessibility & Inclusive Design

His specialization in teaching blind and visually impaired students, particularly those with additional disabilities, has given Dr. Hunsaker deep expertise in accessible pedagogy and non-visual problem-solving. He grounds all curriculum design in evidence-based practice informed by neuroscience, accessibility research, and years of direct classroom experience with diverse learners. He understands that accessibility is not an afterthought or accommodation; it is the foundation upon which effective education for all students is built.

Creator of Accessible Educational Resources

Motivated by observing persistent gaps in affordable, practical, and culturally responsive accessible educational materials, Dr. Hunsaker created TVI Resources, a collection of free, openly licensed instructional materials designed to meet the real needs of educators and students. This commitment to accessible education informed his development of this curriculum: a comprehensive, text-based approach to 3D design and digital fabrication specifically engineered for blind and visually impaired learners, emphasizing independence, technical mastery, and real-world application.

Acknowledgements

This curriculum stands on the shoulders of innovators, educators, and open-source maintainers whose commitment to accessibility and open education made this work possible.

3DMake

Special thanks to Troy Deck, the creator and maintainer of 3DMake, an open-source command-line tool that automates the workflow from code-based 3D models to print-ready files. 3DMake is essential to this curriculum-it eliminates the visual GUI entirely and makes parametric 3D design accessible to screen reader users through text-based commands and configuration files. Without 3DMake, a truly non-visual pathway from design to fabrication would not exist.

Texas School for the Blind and Visually Impaired (TSBVI)

This curriculum was directly inspired by the innovative work at TSBVI, a pioneer in accessible education for blind and visually impaired students. The foundational idea of using text-driven tools and command-line workflows for technical education originated from collaboration with TSBVI educators. Their commitment to demonstrating that blind and visually impaired students can excel in technical fields provided the vision for this project.

OpenSCAD Community

Deep appreciation to the OpenSCAD project maintainers and contributors for creating and maintaining a code-driven, parametric 3D modeling system that is inherently more accessible than traditional GUI-based CAD tools. OpenSCAD’s text-based programming model and screen-reader-compatible approach to geometry design makes it uniquely suited for learners who use assistive technology. The OpenSCAD community’s commitment to open-source principles and accessibility embodies the philosophy that drives this curriculum.

Open Education & Accessibility Movement

Finally, this curriculum is part of a broader movement toward open educational resources that prioritize accessibility from the ground up. It reflects the conviction that education should be barrier-free, that students with disabilities bring unique perspectives and strengths, and that accessible design benefits all learners. The work of accessibility advocates, neurodivergent educators, and disability justice activists informed every decision in building this material.