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:
- Screen Reader Accessibility Guide - Comprehensive NVDA & JAWS reference with terminal tips for PowerShell, CMD, and Git Bash
- Screen Reader Choice: Windows CLI - Help choosing between NVDA and JAWS
- Braille Display & Terminal Mode - Advanced accessibility setup with refreshable braille displays
- Editor Selection and Setup - Choosing and configuring an accessible text editor
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
PowerShell Foundation (Recommended for Windows Users)
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
| Part | Lessons | Focus | Duration |
|---|---|---|---|
| Foundations | 1-3 | Environment setup, primitives, parametric design + advanced language features | 4-5 hours |
| Verification & Safety | 4-5 | AI verification, safety protocols, materials | 2-3 hours |
| Applied Projects | 6-8 | Practical commands, text functions, transforms, assembly patterns | 5-6 hours |
| Advanced Topics | 9-10 | Automation with file I/O, troubleshooting, mastery | 3-4 hours |
| Leadership | 11 | Stakeholder-centric design | 2-3 hours |
Total: 45-55 hours instruction + practice projects
Reference Appendices
Command Line Tools:
- Appendix A: Command Line (CMD/Batch) Integration for SCAD Workflows - Batch processing and automation for CMD users
- Appendix B: PowerShell Integration for SCAD Workflows - Batch processing, automation scripts, and advanced workflow integration for PowerShell users
- Appendix C: Git Bash / POSIX Shell Integration for SCAD Workflows - Shell scripting and automation for Git Bash / Unix shell users
3dMake:
- 3DMake CLI Cheat Sheet - Quick reference for 3dm command-line tool
- Appendix A: Comprehensive Slicing Guide - Complete reference for PrusaSlicer, Bambu Studio, Cura, and OrcaSlicer configuration
- Appendix B: Material Properties & Selection Guide - Detailed material reference including shrinkage data, print settings, and properties
- Appendix C: Tolerance Testing & Quality Assurance Matrix - Comprehensive QA procedures and tolerance validation methods
- Appendix D: Advanced OpenSCAD Concepts - Specialized topics including gears, batch processing, performance, print orientation, and recursion
- 3dMake Code Examples & Assets - OpenSCAD code examples and reference designs
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 buildto 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:
- Official OpenSCAD Documentation - Complete language reference and user manual on Wikibooks. Fully accessible and searchable.
- OpenSCAD Tutorial - Official beginner tutorial covering core concepts and syntax.
- OpenSCAD Cheat Sheet (Official) - Quick reference for all OpenSCAD commands and functions.
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:
- Thingiverse OpenSCAD Designs - Community-created parametric designs with source code available for study and modification.
- OpenSCAD Forums - Active community support for troubleshooting and learning.
- OpenSCAD Tutorials (YouTube) - Video tutorials (note: supplemental to text-based curriculum; transcripts recommended for accessibility).
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:
- Start with Screen Reader Accessibility Guide - Configure NVDA/JAWS for terminal work
- Review Screen Reader Choice: Windows CLI - Help choosing between NVDA and JAWS
- Optional: Braille Display & Terminal Mode - Refreshable braille display configuration
- Complete Editor Selection and Setup - Choose and configure an accessible text editor
Step 2: Choose Your Command Line Pathway
Read Command Line Interface Selection Guide to compare all three CLI options, then select ONE pathway:
- PowerShell Curriculum Overview - Recommended for Windows users
- CMD Curriculum Overview - Simplified alternative for beginners
- Git Bash Curriculum Overview - Cross-platform Unix skills
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:
- Read 3dMake Introduction - Overview of OpenSCAD and 3dMake
- Start Lesson 1: Environmental Configuration - Install OpenSCAD and 3dMake
- Progress through Lessons 2-11 sequentially
- Complete all project templates as you encounter them
- 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:
- Review Syllabus - Complete course structure, philosophy, learning objectives, and assessment framework
- Read 3dMake Foundation Curriculum Guide - Detailed lesson-by-lesson breakdown with timing and objectives
- Study Master Rubric - Comprehensive project assessment criteria
- 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:
- Ensure all students complete Screen Reader Setup before beginning coursework
- Reference Screen Reader Coding Tips (NVDA & JAWS) for troubleshooting student screen reader issues
- Provide access to Student Glossary for terminology reference
Additional Resources:
- Technical Reference - Advanced troubleshooting and systems architecture
- Further Reading - Peer-reviewed research supporting curriculum design
- Quick Reference - At-a-glance lesson and command reference for student handouts
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
-
Text-First Design: All core work happens in text editors and command-line interfaces - no graphical CAD previews, no mouse-dependent menu navigation.
-
Parametric Thinking: Students learn to express geometry as code using OpenSCAD, enabling precise, reproducible, and iterable designs without visual feedback.
-
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.
-
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.
-
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.
| Component | Duration | Content |
|---|---|---|
| Screen Reader Accessibility Guide | 1-1.5 hours | NVDA/JAWS reference for PowerShell, CMD, and Git Bash; keyboard shortcuts |
| Screen Reader Choice: Windows CLI | 30 min | Comparing NVDA, JAWS, Narrator, and Dolphin; choosing the right tool |
| Braille Display & Terminal Mode | 30 min | Optional: configuring refreshable braille displays for terminal work |
| Editor Selection and Setup | 30 min | Choosing 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.
Pathway A: PowerShell Foundation (Recommended for Windows)
Total Duration: 30-45 hours Start here: PowerShell Curriculum Overview
| Component | Duration | Content |
|---|---|---|
| PowerShell Introduction | 20-30 min | Screen-reader-friendly quick-start (JAWS/NVDA); essential commands overview |
| PowerShell Tutorial | 30-45 min | Hands-on tutorial: paths, navigation, wildcards, running scripts |
| Powershell Lesson Pre: Your First Terminal | 2-2.5 hours | Opening PowerShell, first commands, basic navigation, screen reader tricks |
| Powershell Lesson 0: Getting Started | 1.5 hours | Paths, shortcuts, tab completion |
| Powershell Lesson 1: Navigation | 2-2.5 hours | Moving around the file system confidently |
| Powershell Lesson 2: File & Folder Manipulation | 2.5-3 hours | Creating, editing, moving, copying, deleting files and directories |
| Powershell Lesson 3: Input, Output & Piping | 2.5-3 hours | Redirecting output, piping commands, understanding data flow |
| Powershell Lesson 4: Environment Variables & Aliases | 2-2.5 hours | Setting variables, creating shortcuts, persistent configurations |
| Powershell Lesson 5: Filling in the Gaps | 2.5-3 hours | Control flow, profiles, useful tricks, scripting fundamentals |
| Powershell Lesson 6: Advanced Terminal Techniques | 4-4.5 hours | Scripts, functions, loops, professional workflows, automation patterns |
| PowerShell Unit Test & Practice | 2-3 hours | Practice 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
| Component | Duration | Content |
|---|---|---|
| Command Line Lesson Pre: Your First Terminal | 2-2.5 hours | Opening CMD, first commands, basic navigation, screen reader tricks |
| Command Line Lesson 0: Getting Started | 1.5 hours | Paths, shortcuts, command basics |
| Command Line Lesson 1: Navigation | 2-2.5 hours | Moving around the file system confidently |
| Command Line Lesson 2: File & Folder Manipulation | 2.5-3 hours | Creating, editing, moving, copying, deleting files and directories |
| Command Line Lesson 3: Input, Output & Redirection | 2-2.5 hours | Redirecting output, piping commands, understanding data flow |
| Command Line Lesson 4: Environment Variables & Shortcuts | 2-2.5 hours | Setting variables, creating shortcuts, persistent configurations |
| Command Line Lesson 5: Filling in the Gaps | 2.5-3 hours | Batch files, advanced techniques, scripting fundamentals |
| Command Line Lesson 6: Advanced Terminal Techniques | 3-3.5 hours | Scripts, automation patterns, professional workflows |
| CMD Unit Test & Practice | 2-3 hours | Practice 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
| Component | Duration | Content |
|---|---|---|
| Git Bash Introduction | 20-30 min | Screen-reader-friendly quick-start (JAWS/NVDA); essential commands |
| Git Bash Tutorial | 30-45 min | Hands-on tutorial: paths, navigation, wildcards, running scripts |
| Screen Reader Accessibility Guide for Git Bash | 30-45 min | NVDA and JAWS configuration specific to Git Bash |
| Bash Lesson Pre: Your First Terminal | 2-2.5 hours | Opening Git Bash, first commands, basic navigation, screen reader tricks |
| Bash Lesson 0: Getting Started | 1.5 hours | Unix-style paths, shortcuts, command basics, Windows path conversion |
| Bash Lesson 1: Navigation | 2-2.5 hours | Moving around the file system confidently |
| Bash Lesson 2: File and Folder Manipulation | 2-2.5 hours | Creating, editing, moving, copying, deleting files and directories |
| Bash Lesson 3: Input, Output & Piping | 2-2.5 hours | Redirecting output, piping with grep/sort/wc, understanding data flow |
| Bash Lesson 4: Environment Variables & Aliases | 1.5-2 hours | Setting variables, creating aliases, editing .bashrc |
| Bash Lesson 5: Filling in the Gaps | 2-2.5 hours | Shell profiles, command history, debugging |
| Bash Lesson 6: Advanced Terminal Techniques | 2.5-3.5 hours | Shell scripts, functions, loops, professional workflows |
| GitBash Unit Test & Practice | 2-2.5 hours | Practice 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)
| Lesson | Focus | Duration | Project |
|---|---|---|---|
| Lesson 1 | Environmental Configuration + Code Documentation Standards | 60-90 min | None |
| Lesson 2 | Primitives & Boolean Operations + Modifier Characters Debugging | 75-90 min | None |
| Lesson 3 | Parametric Architecture + Advanced Programming Concepts | 90-120 min | None |
Verification & Safety (Lessons 4-5 | ~2 hours)
| Lesson | Focus | Duration | Project |
|---|---|---|---|
| Lesson 4 | AI-Enhanced Verification & Feedback | 45-60 min | None |
| Lesson 5 | Safety Protocols & Material Introduction | 60-90 min | None |
Applied Projects (Lessons 6-8 | ~5-6 hours)
| Lesson | Focus | Duration | Project |
|---|---|---|---|
| Lesson 6 | Practical 3dm Commands + String Functions | 75-105 min | Customizable Keycap |
| Lesson 7 | Parametric Transforms + Math Functions | 90-120 min | Phone Stand |
| Lesson 8 | Advanced Design + Assembly Best Practices | 105-150 min | Stackable Bins |
Advanced Topics (Lessons 9-10 | ~3-4 hours)
| Lesson | Focus | Duration | Project |
|---|---|---|---|
| Lesson 9 | Automation + File Import/Export (requires CLI Foundation) | 75-105 min | Batch Processing Automation |
| Lesson 10 | Troubleshooting & Mastery with Measurement | 120-150 min | QA Testing + Accessibility Audit |
Leadership (Lesson 11 | ~2 hours)
| Lesson | Focus | Duration | Project |
|---|---|---|---|
| Lesson 11 | Stakeholder-Centric Design & Design Thinking | 90-120 min | Beaded Jewelry Holder |
Total: 16-20 hours of instruction + projects
Reference Appendices
Overview Documents
- CLI Appendices Overview - Summary of all command line integration guides
- 3dMake Appendices Overview - Summary of all 3dMake reference materials
Command Line Integration Appendices
Located in Command_Line_Interface_Selection/:
| Appendix | Title | Use When |
|---|---|---|
| Appendix A | CMD/Batch Integration for SCAD Workflows | Automating with Windows Command Prompt and batch files |
| Appendix B | PowerShell Integration for SCAD Workflows | Automating with PowerShell scripts and advanced workflows |
| Appendix C | Git Bash / POSIX Shell Integration for SCAD | Automating with Unix/bash shell scripts for cross-platform |
3dMake & OpenSCAD Appendices
Located in 3dMake_Foundation/:
| Appendix | Title | Use When |
|---|---|---|
| 3DMake Cheat Sheet | Complete 3dm CLI Reference | Quick command lookup, troubleshooting 3dm commands |
| Appendix A | Comprehensive Slicing Guide | Slicing questions, switching slicers, quality issues |
| Appendix B | Material Properties & Selection Guide | Choosing material, troubleshooting prints, cost analysis |
| Appendix C | Tolerance Testing & Quality Assurance Matrix | Starting a project, verifying dimensions, quality issues |
| Appendix D | Advanced OpenSCAD Concepts | Building mechanical systems, optimizing complex models |
| Code Examples & Assets | 3dMake Code Examples & Assets | Reference 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
- 3dMake Foundation Curriculum Guide - Detailed lesson-by-lesson breakdown with objectives and timing
- 3dMake Quick Reference - At-a-glance command and syntax reference
Learning Progression: Student Roles
Students move through roles across the curriculum:
| Phase | Role | Core Tools | Focus |
|---|---|---|---|
| CLI Foundation | Observer/Learner | Terminal, command line | CLI fundamentals and keyboard navigation |
| 3dMake Lessons 1-5 | Observer/Learner | OpenSCAD, 3DMake, editor | Using CLI tools, safety, concepts, measurement |
| 3dMake Lessons 6-8 | Operator | Editor, OpenSCAD, 3DMake, slicer | Hands-on practice with structured projects |
| 3dMake Lessons 9-10 | Designer | Full toolchain | Parametric design, automation, troubleshooting |
| 3dMake Lesson 11 | Problem-Solver | Full toolchain + documentation | Stakeholder 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
| Section | Prerequisites | What You’ll Learn |
|---|---|---|
| Setup | None - start here | Screen reader optimization, editor selection, accessibility setup |
| CLI Foundation | Setup | Terminal basics, keyboard navigation, file operations, basic scripting |
| 3dMake Lessons 1-5 | Setup (CLI Foundation recommended) | 3D printing concepts, safety, measurement, OpenSCAD basics, debugging |
| 3dMake Lessons 6-8 | Lessons 1-5 | Building projects, parametric design, transforms, tolerances |
| 3dMake Lessons 9-10 | Lessons 6-8 + CLI Foundation required | Automation, troubleshooting, advanced measurement and QA |
| 3dMake Lesson 11 | Lessons 9-10 | Stakeholder design, real-world prototyping, leadership |
Grading Rubric
All projects are scored on a 0-9 scale across three equally weighted categories (3 points each):
| Category | Points | What We Measure |
|---|---|---|
| Problem & Solution | 0-3 | Does the design solve the stated problem? Are all functional requirements met? |
| Design & Code Quality | 0-3 | Is the OpenSCAD code clean, well-commented, and well-structured? Does the print work well? Is there evidence of iteration? |
| Documentation | 0-3 | Are all sections complete? Are reflections thoughtful and specific? Are measurements recorded? |
Category 1: Problem & Solution (0-3 points)
| Score | Description |
|---|---|
| 3 | The prototype clearly and effectively solves the stated problem. All functional requirements are met. The solution shows evidence of testing against the requirements. |
| 2 | The prototype mostly meets the problem. Most functional requirements are met. Minor gaps between the design and the requirements. |
| 1 | The prototype partially addresses the problem. Several functional requirements are not met or were not clearly tested. |
| 0 | The 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.
| Score | Description |
|---|---|
| 3 | Code 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. |
| 2 | Code works but lacks clear structure or comments. Variables are used but could be better named. Print quality is acceptable. Some iteration evident. |
| 1 | Code is functional but poorly organized. Comments are minimal or missing. Print quality has defects. Little or no iteration. |
| 0 | Code does not work, is not submitted, or shows no original thinking. Print is not functional. |
Category 3: Documentation (0-3 points)
| Score | Description |
|---|---|
| 3 | All required sections are present, complete, and specific. Reflections are thoughtful and reference specific decisions, problems encountered, and learning. Photos/measurements are included. |
| 2 | Most required sections are present. Some sections are vague or missing detail. Reflections show some thought but are brief or generic. |
| 1 | Documentation is incomplete. Major sections are missing or consist of one-line responses. Reflections are minimal. |
| 0 | Documentation is not submitted or is essentially empty. |
Score Interpretation
| Total Score | Interpretation | Next Step |
|---|---|---|
| 8-9 | Excellent work | Move on to next project |
| 6-7 | Good work with room for improvement | Move on; instructor may suggest revisiting one element |
| 4-5 | Meets basic expectations | Resubmission of specific weak areas recommended |
| 2-3 | Does not meet expectations | Resubmission required |
| 0-1 | Missing major deliverables | Meet 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.
Quick Links to Essential Tools & Setup
Core Design Toolchain
OpenSCAD
- OpenSCAD Download - Free, cross-platform CAD (all major OS)
- OpenSCAD Documentation - Official reference
- OpenSCAD Cheat Sheet - Quick syntax reference
3DMake
- 3DMake Documentation & Installation - Command-line build tool for OpenSCAD
- 3DMake CLI Cheat Sheet - Complete command reference
- 3dMake Quick Reference - Command and workflow reference
Editors
- VS Code Download - Free, screen-reader-accessible code editor
- Notepad++ Download - Free, lightweight Windows editor
- Editor Selection and Setup Guide - Accessibility-focused setup guide
Screen Reader & Accessibility
Screen Readers
- NVDA Download - Free, open-source screen reader (Windows)
- JAWS Screen Reader - Commercial screen reader (Windows, macOS)
- Orca Screen Reader - Built-in screen reader for Linux/GNOME desktop
- Windows Narrator - Built-in Windows screen reader
- Dolphin SuperNova - Commercial screen reader (Windows)
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
- Screen Reader Accessibility Guide - Comprehensive terminal accessibility guide
- Screen Reader Coding Tips (NVDA & JAWS) - Keyboard shortcuts and configuration
- VSCode Setup Guide - Accessibility-focused editor configuration
- Git Bash Screen Reader Guide - NVDA and JAWS configuration for Git Bash
Slicing Software
- PrusaSlicer
- Bambu Studio
- Cura
- OrcaSlicer
- Appendix A: Comprehensive Slicing Guide - Detailed setup guides for all major slicers
Supplemental Textbooks & Learning Resources
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. 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.
- Mastering OpenSCAD by Jochen Kerdels - Project-based learning approach with emphasis on parametric design and reusable code modules.
Free Online Resources:
- Official OpenSCAD Documentation - Complete language reference and user manual on Wikibooks. Fully accessible and searchable.
- OpenSCAD Tutorial - Official beginner tutorial covering core concepts and syntax.
- OpenSCAD Cheat Sheet (Official) - Quick reference for all OpenSCAD commands and functions.
Curriculum-Specific Resources:
- Programming with OpenSCAD Companion Resources - Practice worksheets for visualization, 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:
- Thingiverse OpenSCAD Designs - Community-created parametric designs with source code for study and modification.
- OpenSCAD Forums - Active community support for troubleshooting and learning.
- OpenSCAD Tutorials (YouTube) - Video tutorials (note: supplemental to text-based curriculum; transcripts recommended for accessibility).
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
- County Library “Create” Spaces
- Hardware: Flashforge Adventurer 5M Pro, LulzBot Workhorse, laser cutters
- Pricing: $0.06 per gram of filament used
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:
- 3dMake Setup Guide - Installation walkthrough
- VSCode Setup Guide - Accessibility-focused editor configuration
- mdBook Navigation Guide - How to navigate this curriculum
Syntax & Commands:
- OpenSCAD Cheat Sheet - Complete syntax quick-reference
- 3DMake CLI Cheat Sheet - All 3dm commands and options
Materials & Safety:
- Filament Comparison Table - Material selection guide
- Safety Checklist - Pre-print safety procedures
- Maintenance Log - Printer maintenance tracking
When You’re Stuck
For Technical Issues:
- Check Common Issues and Solutions - Comprehensive troubleshooting guide
- Review Diagnostic Checklist - Systematic problem diagnosis
- Consult Technical Reference - Advanced systems architecture and professional reference
- Post in OpenSCAD Discord or Reddit r/openscad
- Visit your local makerspace for hands-on support
For Accessibility Support:
- Contact your NVDA/JAWS vendor directly for technical assistance
- Refer to the Screen Reader Accessibility Guide
- Review Screen Reader Coding Tips (NVDA & JAWS)
- Check the Git Bash Screen Reader Guide if using Git Bash
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
| Section | Title |
|---|---|
| Part 1: Choosing a Screen Reader | Compare NVDA, JAWS, Windows Narrator, and Dolphin SuperNova for command-line work |
| Part 2: Screen Reader Accessibility Guide | Key commands and terminal strategies for all four screen readers |
| Part 3: Braille Display Setup | Connecting and configuring a braille display with any screen reader |
| Part 4: Editor Selection and Setup | Choosing 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.
| Task | NVDA | JAWS | Windows Narrator | Dolphin SuperNova |
|---|---|---|---|---|
| Read current line or prompt | NVDA+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 here | NVDA+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 output | Up Arrow in review mode | Insert+Up Arrow (line by line) | Narrator+Up Arrow (scan mode) | CapsLock+Numpad 8 |
| Move to next line of output | Down Arrow in review mode | Insert+Down Arrow (line by line) | Narrator+Down Arrow (scan mode) | CapsLock+Numpad 2 |
| Jump to end of screen/buffer | NVDA+End | Insert+End | Narrator+End | CapsLock+Page Down |
| Jump to start of screen/buffer | NVDA+Home | Insert+Home | Narrator+Home | CapsLock+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 reading | Ctrl | Ctrl | Ctrl | Ctrl |
| Open screen reader settings | NVDA+N > Preferences | Insert+F3 > Options/Settings | Windows+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
-
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.
-
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.txtThis works in CMD, PowerShell, and Git Bash, and gives you a stable document that all four screen readers can read comfortably.
-
Braille display users can use a braille display alongside any of these four screen readers. See the Braille Display Setup guide for detailed instructions.
-
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
| Screen Reader | Official Documentation | Support / Help |
|---|---|---|
| NVDA | https://www.nvaccess.org/ | https://www.nvaccess.org/download/ |
| JAWS | https://www.freedomscientific.com/products/software/jaws/ | https://www.freedomscientific.com/downloads/jaws/ |
| Windows Narrator | https://support.microsoft.com/narrator | https://support.microsoft.com/narrator |
| Dolphin SuperNova | https://yourdolphin.com/supernova/ | https://yourdolphin.com/supernova/ |
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
- Which Terminal Should I Use?
- Getting Started with Screen Readers
- NVDA-Specific Tips
- JAWS-Specific Tips
- Windows Narrator-Specific Tips
- Dolphin SuperNova-Specific Tips
- General Terminal Accessibility
- Working with Long Output
- Keyboard Shortcuts Reference
- Shell-Specific Differences
- 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:
| Feature | PowerShell | CMD | Git Bash |
|---|---|---|---|
| Platform | Windows only | Windows only | Windows, macOS, Linux |
| Screen Reader Support | Excellent | Excellent | Excellent |
| Learning Curve | Moderate | Gentle | Moderate-Steep |
| Use Case | Modern automation | Familiar simplicity | Cross-platform/Git workflows |
| Recommended For | 3D design automation | Getting started easily | Software 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:
| Feature | NVDA | JAWS | Windows Narrator | Dolphin SuperNova |
|---|---|---|---|---|
| Cost | Free (open-source) | Commercial (paid) | Free (built into Windows) | Commercial (paid) |
| Installation | Simple download | Complex but thorough | Already installed | Standard installer |
| Terminal Support | Excellent (all shells) | Excellent (all shells) | Good (all shells) | Good (all shells) |
| Learning Curve | Gentle | Steeper | Minimal | Moderate |
| Customization | Good (add-ons) | Extensive (scripts) | Limited | Good |
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
- Make sure your screen reader is running before opening your terminal.
- Open your terminal (PowerShell, CMD, or Git Bash) and let your screen reader read the title and prompt.
- If you do not hear anything, press Alt+Tab to cycle windows and find your terminal.
- 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
| Command | What It Does |
|---|---|
| NVDA+Home | Read the current line (your command or output) |
| NVDA+Down Arrow | Read from cursor position to end of screen |
| NVDA+Up Arrow | Read from top of screen to cursor |
| NVDA+Page Down | Read next page |
| NVDA+Page Up | Read previous page |
| NVDA+F7 | Open the Elements List / Review Mode viewer |
| NVDA+Shift+Right Arrow | Read next word |
| NVDA+Shift+Down Arrow | Read entire visible screen |
| NVDA+End | Jump to end of line |
| NVDA+Home | Jump to start of line |
| NVDA+Numpad 5 | Announce the character under the review cursor |
| NVDA+Shift+Numpad 5 | Announce 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:
- After the command finishes, press NVDA+Home to read the current line.
- Press NVDA+Down Arrow repeatedly to read all output line by line.
- Or redirect to a file first:
command > output.txt, then open withnotepad output.txtfor more comfortable reading.
NVDA Settings for Terminals
- Press NVDA+N to open the NVDA menu.
- Go to Preferences > Settings > Speech.
- Increase or decrease verbosity to taste.
- Under Document Formatting, enable “Report indentation” (important for reading code).
- 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
| Command | What It Does |
|---|---|
| Insert+Down Arrow | Read all / say all from cursor downward |
| Insert+Up Arrow | Re-read current line |
| Insert+Page Down | Read next page of terminal output |
| Insert+Page Up | Read previous page of terminal output |
| Insert+End | Jump to end of text on screen |
| Insert+Home | Jump to start of text on screen |
| Insert+Ctrl+Down | Read to end of screen |
| Insert+Ctrl+Up | Read to beginning of screen |
| Insert+Shift+Page Down | Select and read next page |
| Insert+F3 | Open JAWS menu |
| Insert+Z | Toggle JAWS virtual cursor on/off |
| Insert+F2 | Open 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:
- Open the file in Notepad:
notepad file.txt - In Notepad, press Insert+Ctrl+Down to hear all content from the top.
- Use Insert+Down Arrow to read line by line at your own pace.
- Use Insert+F (JAWS Find) to search for specific text within the file.
JAWS Settings for Terminals
- Press Insert+F3 to open the JAWS menu.
- Go to Options > Settings Center (or Utilities > Settings Manager in older versions).
- Search for “terminal” or “console”.
- Enable “Announce output” and verify “Speak when program speaks” is on.
- 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
| Command | What It Does |
|---|---|
| Narrator+D | Read current line |
| Narrator+M | Read next line |
| Narrator+I | Read current item or focused element |
| Narrator+R | Read from cursor / read all from here |
| Narrator+Ctrl+R | Read page / read all |
| Narrator+Left/Right Arrow | Move to previous/next item |
| Narrator+Up/Down Arrow | Move to previous/next line in scan mode |
| Narrator+Enter | Activate/interact with current item |
| Narrator+Space | Toggle Narrator scan mode (browse vs. type mode) |
| Narrator+F1 | Open Narrator help |
| Windows+Ctrl+Enter | Start 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
- Open Settings > Accessibility > Narrator.
- Under “Change what you hear when typing”, enable “Hear characters as you type”.
- Under “Change what Narrator reads”, enable “Read hints for controls and buttons”.
- Set verbosity level to 3 or 4 for a good balance of detail.
- 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
| Command | What It Does |
|---|---|
| Caps Lock+Down Arrow (or NumPad 2) | Read current line |
| Caps Lock+Numpad 5 | Read current word |
| Caps Lock+Numpad 6 | Read next word |
| Caps Lock+Numpad 4 | Read previous word |
| Caps Lock+Numpad 8 | Read from cursor to top |
| Caps Lock+Numpad 2 | Read from cursor to bottom |
| Caps Lock+Numpad Plus | Say all / read all from current position |
| Caps Lock+L | Re-read current line |
| Caps Lock+Right Arrow | Read next character |
| Caps Lock+Left Arrow | Read previous character |
| Caps Lock+Page Down | Jump to end of document or screen |
| Caps Lock+Page Up | Jump 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
- Open SuperNova before opening your terminal application.
- Dolphin SuperNova automatically tracks focus as you move between the editor, terminal, and file explorer.
- In the terminal, use the Dolphin key+Numpad Plus (say all) to have the screen read after running a command.
- For complex output, redirect to a file and open in Notepad:
command > output.txt, thennotepad output.txt.
Dolphin SuperNova Settings for Terminals
- Open SuperNova Control Panel (press Caps Lock+SpaceBar, or click the SuperNova icon).
- Go to Speech > Verbosity and set a comfortable level (3 or 4 recommended for terminal work).
- Go to Speech > Text Processing > Indentation and enable indentation announcement (important for code).
- Go to Braille > Settings if you are using a braille display alongside speech.
- 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:
- Title bar: Window name (e.g., “Windows PowerShell”, “Command Prompt”, “Git Bash”)
- Content area: Command history and output
- 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).
Navigation Sequence
When you open any terminal:
- Your screen reader announces the window title.
- Then it announces the prompt line.
- Anything before the prompt is previous output.
- 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:
Solution 1: Redirect to a File (Recommended)
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)
| Key | Action | Why It Matters |
|---|---|---|
| Up Arrow | Show previous command | Repeat commands without retyping |
| Down Arrow | Show next command | Navigate through history |
| Tab | Auto-complete path or command name | Faster and more accurate |
| Shift+Tab | Cycle backward through completions | If Tab went too far |
| Home | Jump to start of command line | Edit beginning of a command |
| End | Jump to end of command line | Edit end of a command |
| Ctrl+A | Select all text on line | Copy entire command |
| Ctrl+C | Stop / interrupt running command | Abort long-running tasks |
| Ctrl+L | Clear screen | Start fresh visually |
| Enter | Run command | Execute what you typed |
Screen Reader Navigation Quick Reference
| Task | NVDA | JAWS | Windows Narrator | Dolphin SuperNova |
|---|---|---|---|---|
| Read current line | NVDA+Home | Insert+Up Arrow | Narrator+D | CapsLock+L |
| Read all from here | NVDA+Down Arrow | Insert+Ctrl+Down | Narrator+R | CapsLock+Numpad Plus |
| Read next line | Down Arrow (review) | Insert+Down Arrow | Narrator+M | CapsLock+Numpad 2 |
| Read previous line | Up Arrow (review) | Insert+Up Arrow | Narrator+Up Arrow | CapsLock+Numpad 8 |
| Jump to end of output | NVDA+End | Insert+End | Narrator+End | CapsLock+Page Down |
| Jump to start of output | NVDA+Home | Insert+Home | Narrator+Home | CapsLock+Page Up |
| Stop reading | Ctrl | Ctrl | Ctrl | Ctrl |
Shell-Specific Differences
While all three shells work equally well with screen readers, there are differences in commands and syntax:
File Listing and Navigation
| Task | PowerShell | CMD | Git Bash |
|---|---|---|---|
| List files | ls or Get-ChildItem | dir | ls -la |
| List names only | ls -Name | dir /B | ls -1 |
| Change directory | cd path | cd path | cd path |
| Current location | pwd | cd (no args) | pwd |
| Create folder | mkdir foldername | mkdir foldername | mkdir foldername |
| Delete file | Remove-Item file.txt | del file.txt | rm file.txt |
| Home directory | $HOME or ~ | %USERPROFILE% | ~ |
Output Redirection
| Task | PowerShell | CMD | Git Bash |
|---|---|---|---|
| Save to file | command > file.txt | command > file.txt | command > file.txt |
| Append to file | command >> file.txt | command >> file.txt | command >> file.txt |
| Filter output | command | Select-String "text" | command | find "text" | command | grep "text" |
| Open file | notepad file.txt | notepad file.txt | notepad file.txt (Windows) |
Scripting and Automation
| Feature | PowerShell | CMD | Git Bash |
|---|---|---|---|
| File extension | .ps1 | .bat | .sh |
| Comment | # | REM or :: | # |
| Variable | $var = "value" | set var=value | var=value |
| Echo text | Write-Host "text" | echo text | echo text |
| Get help | Get-Help command | help command | man 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:
- 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.
- Output scrolled off-screen — Redirect to file:
command > output.txt, thennotepad output.txt. - Screen reader focus is on window title, not content — Press Tab or arrow keys to move into the content area.
- Large output overwhelming screen reader — Use filtering:
command | grep "pattern"(Git Bash),command | find "text"(CMD), orcommand | Select-String "text"(PowerShell).
Problem 2: “Tab Completion Isn’t Working”
- You must type at least one character before pressing Tab.
- The folder or file must exist — run
dir(CMD),ls(PowerShell/Git Bash) to check. - If multiple matches exist, press Tab again to cycle through them.
Problem 3: “Access Denied or Permission Denied”
- Close your terminal, right-click it, and choose Run as administrator. Confirm the UAC prompt.
- If the file is in use by another program, close that program and try again.
- 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”
- Press Up Arrow to recall the previous command.
- Use Left/Right Arrow keys to move through it.
- 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
- NVDA: https://www.nvaccess.org/
- JAWS: https://www.freedomscientific.com/products/software/jaws/
- Windows Narrator: https://support.microsoft.com/narrator
- Dolphin SuperNova: https://yourdolphin.com/supernova/
- PowerShell Docs: https://example.com
- CMD Documentation: https://example.com
- Git Bash / Git for Windows: https://example.com
- Accessibility Best Practices: https://example.com
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
- Plug the display’s USB cable into your computer.
- 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).
- Open your screen reader’s braille settings and select the connected display.
Bluetooth Connection
- Put the braille display into pairing mode (refer to the device’s quick-start guide).
- On Windows, go to Settings > Bluetooth & devices > Add a device and pair the display.
- 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.
- Connect your display via USB or Bluetooth.
- Open the NVDA menu: press NVDA+N (Insert+N or CapsLock+N depending on your modifier key setting).
- Go to Preferences > Settings > Braille (or press NVDA+Ctrl+B as a shortcut on some versions).
- 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.
- Set your preferred braille output table (e.g., Unified English Braille Grade 1 or Grade 2, or your country’s national table).
- Set “Braille input table” if you want to type commands using the display’s braille keyboard (if equipped).
- Enable “Show cursor” so you can see the caret position on the display.
- 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):
| Action | NVDA Command |
|---|---|
| Pan braille display right | Display’s right pan key |
| Pan braille display left | Display’s left pan key |
| Toggle braille tethered to focus/review | NVDA+Ctrl+T |
| Move to previous braille line | NVDA+Shift+Up (or display key) |
| Move to next braille line | NVDA+Shift+Down (or display key) |
| Open braille settings | NVDA+Ctrl+B (some versions) |
JAWS
JAWS supports a wide range of braille displays through its built-in braille manager and additional vendor drivers.
- Connect your display via USB or Bluetooth.
- Install the vendor’s display driver if required (check the vendor’s website — some displays work without a driver in JAWS, others need one).
- Open the JAWS menu: press Insert+F3 (or your JAWS key+F3).
- Go to Options > Basics > Braille or use the JAWS Settings Center and search for “Braille”.
- In Braille Settings, select your display model from the list.
- Choose your braille translation table (e.g., English Unified Grade 1 for uncontracted, Grade 2 for contracted).
- Configure cursor routing so that pressing a routing button on the display moves the JAWS cursor to that position.
- 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).
- Connect your display via USB or Bluetooth.
- Install the vendor’s display driver if required.
- Open Settings > Accessibility > Narrator > Braille (Windows 11) or Settings > Ease of Access > Narrator > Use Braille (Windows 10).
- Turn on “Install braille” (first-time setup may require downloading the braille translation component — approximately 70 MB).
- Select your display brand and model from the list.
- Choose a braille table (Grade 1 recommended for terminal work).
- 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).
- Connect your display via USB or Bluetooth.
- Install the vendor’s driver if required.
- Open the SuperNova Control Panel: press CapsLock+SpaceBar or click the SuperNova icon in the taskbar.
- Go to Braille > Display and select your display model from the list.
- Go to Braille > Translation and select your braille table (Grade 1 / uncontracted recommended for code).
- Go to Braille > Settings to configure cursor style, word wrap, and other options.
- 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:
- Reading the prompt: The display shows your current prompt (e.g.,
C:\Users\YourName>orPS C:\>). Pan right if the prompt is longer than your display width. - 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.
- Redirecting long output: For long terminal output, redirect to a file and open in Notepad:
In Notepad, you can pan through the braille display comfortably without the output scrolling away.command > output.txt notepad output.txt - 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
| Vendor | Products | Support / Drivers |
|---|---|---|
| HumanWare | Brailliant, BrailleNote Touch+ | https://www.humanware.com/ |
| Freedom Scientific | Focus Blue series | https://www.freedomscientific.com/Products/Blindness/FocusBlue/ |
| HIMS | BrailleSense, Braille EDGE, Smart Beetle | https://www.hims-inc.com/ |
| Optelec | Braille STAR, Easy Link | https://www.optelec.com/ |
| Orbit Research | Graphiti, Orbit 20/40 | https://www.orbitresearch.com/ |
| APH | Monarch | https://www.aph.org/ |
| Dot Inc. | DotPad | https://dotincorp.com/ |
| Dolphin | GuideConnect, braille accessories | https://yourdolphin.com/ |
Connecting a Braille Display: Summary Table
| Screen Reader | Where to Find Braille Settings | Recommended Braille Table for Code |
|---|---|---|
| NVDA | NVDA Menu > Preferences > Settings > Braille | Unified English Braille Grade 1 |
| JAWS | Insert+F3 > Options > Basics > Braille (or Settings Center) | English Braille Grade 1 (uncontracted) |
| Windows Narrator | Settings > Accessibility > Narrator > Braille | English Grade 1 (uncontracted) |
| Dolphin SuperNova | CapsLock+SpaceBar > Braille > Display and Translation | Grade 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
- Editor Comparison
- Editor Setup for 3dMake
- Screen Reader Indent Announcement Configuration
- Curriculum-Specific Editor Recommendations
Editor Comparison
Overview Table
| Feature | Notepad | Notepad++ | Visual Studio Code |
|---|---|---|---|
| Cost | Free (built-in) | Free | Free |
| Learning Curve | Minimal | Low | Moderate |
| Screen Reader Support | Good (basic) | Good (syntax features) | Excellent (built-in accessibility) |
| Extension/Plugin System | None | Limited | Extensive |
| Keyboard Navigation | Good | Good | Excellent |
| Customization | None | Moderate | Very high |
| Performance | Excellent | Very good | Good |
| Syntax Highlighting | None | Yes (OpenSCAD available) | Yes (OpenSCAD available) |
| Terminal Integration | None | None | Built-in |
| Real-time Feedback | None | None | Yes (with extensions) |
| Hot Key Customization | Limited | Good | Excellent |
| File Size Handling | Good | Good | Excellent |
| Built-in Debugging | None | None | Limited |
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:
-
Open 3dMake-generated .scad files directly:
- Navigate to your project folder in File Explorer
- Right-click the
.scadfile -> “Open with” -> “Notepad” - File opens immediately for editing
-
Edit and Save:
- Make changes to your code
- Press
Ctrl+Sto save - File updates automatically if 3dMake renders in background
-
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 ReplaceCtrl+G: Go to Line (newer versions)Ctrl+Z: UndoCtrl+Y: Redo
Notepad++ Setup
Installation and Configuration:
-
Download from: https://notepad-plus-plus.org/downloads/
-
Choose: Standard Installer (for automatic system integration)
-
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)
-
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
-
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:
- Download from: https://code.visualstudio.com/ or type
winget search VSCodein a terminal and thenwinget installwhichever option you prefer - Install: Run installer and follow prompts
- Launch: Open VSCode
Enable OpenSCAD Support:
- Open Extensions (Ctrl+Shift+X)
- Search: “OpenSCAD”
- Install: “scad-preview” by Antyos
- Install: “OpenSCAD Syntax Highlighter” (optional, for better syntax highlighting)
Initial Accessibility Configuration:
-
Open Settings: Ctrl+,
-
Search: “accessibility”
-
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
-
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)
- View -> Terminal (or Ctrl+`)
- Terminal opens at bottom of VSCode window
- Run commands:
3dMake render filename.scad - 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
Option 2: Alt-Tab to Standalone Terminal (RECOMMENDED for Accessibility)
-
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
-
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:
| Action | Shortcut |
|---|---|
| Save | Ctrl+S |
| Find | Ctrl+F |
| Find and Replace | Ctrl+H |
| Go to Line | Ctrl+G |
| Open File | Ctrl+O |
| Open Folder | Ctrl+K, Ctrl+O |
| Open Terminal | Ctrl+` |
| Alt-Tab to Another Window | Alt+Tab |
| Command Palette | Ctrl+Shift+P |
Project Organization in VSCode:
-
Open Project Folder:
- File -> Open Folder (Ctrl+K, Ctrl+O)
- Select your project directory
- All project files appear in Explorer sidebar
-
File Navigation:
- Press Ctrl+P for Quick Open
- Type filename to search and jump to file
- Press Enter to open
-
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:
- Open NVDA Menu: Alt+N or right-click NVDA icon
- Preferences -> Settings (Ctrl+Comma)
- Document Formatting: Tab to it
- Check: “Report indentation”
- In the “Indentation reporting” dropdown: Select “Tones and speech”
- Tone Description: NVDA will announce indent level as progressively higher tones (or speaking indent amount)
- Apply: Click OK
Additional Tab Stop Configuration:
- Preferences -> Settings -> Document Formatting
- Check: “Report line indentation”
- This will announce: “Indent level 4” or similar as you navigate code
Testing:
- Open a
.scadfile 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:
- Open JAWS Manager: Press JAWSKey+F2 (or right-click JAWS icon)
- Utilities -> Settings Manager
- Search: “Indent”
- Look for setting: “Announce Indentation” or “Report Indentation”
- Enable: Set to “Tones” or “Tones and Speech”
- Speech Indent Announcement: Speak indent level
- Tone Indent Announcement: Pitch increases with indent level
Advanced Configuration (Custom Scripts):
If built-in settings don’t work:
- JAWSKey+F2 -> Utilities -> Settings Manager
- Search: “Line Breaks” or “Formatting”
- Ensure: “Report line indentation” is enabled
- Set tone adjustment: Higher pitch for deeper indents
Testing:
- Open
.scadfile 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:
- Open Settings: Win+I
- Ease of Access -> Narrator
- Advanced Options: Scroll down
- Check: “Report indentation”
- Indentation Reporting: Select “Tones” (less intrusive) or “Speech” (explicit)
- 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
.scadfile - 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:
- Open Dolphin Central: Right-click Dolphin icon or click Dolphin icon in taskbar
- Utilities -> Settings -> Text Processing
- Look for: “Indentation” section
- Enable: “Announce indentation”
- Mode: Select “Tones”, “Speech”, or “Tones and Speech”
- Tone Pitch: Configure pitch increase for deeper indents
- Apply
ECO (Ease of Cursor Operation) Customization:
- Dolphin Central -> Utilities -> ECO Settings
- Text Options -> Indentation Reporting
- Set preferred announcement style
Testing:
- Open
.scadfile 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:
- Use Notepad or Notepad++ as default editor
- Configure screen reader indent announcement
- Keep separate Command Prompt window open for 3dMake commands
- 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:
-
Create custom keyboard shortcuts:
- Ctrl+Alt+R: Save and render current file
- Ctrl+Alt+P: Preview (if using scad-preview extension)
-
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
-
Create Task Runner for Common Commands:
- Ctrl+Shift+B: Configure build task to run 3dMake
- Create separate tasks for render, export, etc.
-
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:
- Verify indent announcement is enabled in screen reader settings (see above)
- Test with existing
.scadfile with clear indentation - Try different announcement modes (tones vs. speech)
- Restart screen reader: Alt+Ctrl+N (NVDA) or app restart (JAWS)
Problem: 3dMake Commands Not Running from VSCode Terminal
Solution:
- Ensure 3dMake is in your system PATH
- Use standalone terminal instead (Alt-Tab method) - more reliable
- In VSCode terminal, manually navigate to correct directory first
- Verify command syntax:
3dMake render filename.scad
Problem: File Not Saving in Editor
Solution:
- Verify you pressed Ctrl+S
- Check file permissions on project folder
- Try “Save As” instead
- Ensure filename includes
.scadextension
Problem: Syntax Highlighting Not Working
Solution:
- Verify file has
.scadextension - In Notepad++: Language menu -> select OpenSCAD or C++
- In VSCode: Install OpenSCAD extension (search Extensions)
- Restart editor
Problem: Alt-Tab Not Switching Between Windows
Solution:
- Ensure Command Prompt is open and minimized (not closed)
- Press Alt+Tab and hold briefly to see window switcher
- Use Alt+Tab multiple times if more than 2 windows open
- Alternatively, click taskbar directly (Alt+Tab usually more accessible)
Next Steps
After completing this setup guide:
- Choose your editor based on the recommendations for your skill level
- Configure screen reader indent announcement immediately (critical for code structure understanding)
- Set editor as default for
.scadfiles - Test with a simple file: Create a test project and edit it
- Practice Alt-Tab workflow before moving to Lesson 1
- Document your setup in a personal note for reference
You are now ready to begin Lesson 1: Environmental Configuration and Developer Workflow
Additional Resources
- NVDA Documentation: https://www.nvaccess.org/documentation/
- JAWS Documentation: https://www.freedomscientific.com/products/software/jaws/
- VSCode Accessibility: https://code.visualstudio.com/docs/editor/accessibility
- Windows Narrator Guide: https://support.microsoft.com/en-us/help/22798/windows-11-narrator-get-started
- Notepad++ Documentation: https://notepad-plus-plus.org/online-help/
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.
| Material | Fume Risk | Required Mitigation |
|---|---|---|
| PLA | Low | Good room ventilation (open window or HVAC on) |
| PETG | Low–Medium | Active ventilation; avoid enclosed spaces without air exchange |
| 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
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:
| Filament | Strength | Flexibility | Heat Resistance | Print Difficulty | Best Uses |
|---|---|---|---|---|---|
| PLA | Medium | Rigid | Low (softens at 50–60°C) | Easy | Prototypes, display models, artwork, educational parts |
| PETG | Medium-High | Slightly flexible | Medium (75–80°C) | Easy–Medium | Functional parts, food-adjacent applications, water contact |
| ABS | High | Semi-rigid | High (85–100°C) | Hard | Hot environments, automotive interiors, post-processing (acetone smoothing) |
| TPU | Medium | Very flexible | Medium | Medium | Gaskets, grips, phone cases, flexible joints |
| Nylon | Very High | Flexible | High | Hard | Mechanical parts, gears, load-bearing functional parts |
| ASA | High | Semi-rigid | Very High (90°C+) | Hard | Outdoor 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:
-
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.
-
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.
-
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.
-
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)
- What are the five levels of the Hierarchy of Controls, from most to least effective?
- Why is Elimination considered the most effective safety control?
- Which filament requires a dedicated fume enclosure with HEPA + activated carbon filtration and is NOT recommended for open classrooms?
- At what temperature should you wait before removing a print from the bed?
- What should you do immediately if you see smoke coming from your 3D printer?
- Give three reasons why PLA is considered the safest classroom filament.
- What is the minimum reliable wall thickness for a 0.4 mm nozzle, and why does this minimum exist?
- What is the purpose of storing filament with desiccant?
- True or False: It is safe to leave a 3D printer completely unattended for hours once the first layer has printed successfully.
- What is “spaghetti” in the context of a 3D printing failure, and what causes it?
- What is thermal runaway protection, and why is it critical that it remain enabled?
- What are the two types of airborne emissions from FDM printing, and which filaments produce the most hazardous levels of each?
- Describe one engineering control and one administrative control you could implement in a classroom 3D printing lab.
- Explain why minimizing overhangs in your design is both a safety consideration and a quality consideration.
- 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)
- Create a material selection flowchart that guides a user from mechanical requirements to the safest filament that meets them.
- Conduct a ventilation assessment of your classroom or makerspace. Document air exchange methods, window locations, and any existing filtration.
- Write a Standard Operating Procedure (SOP) for ABS printing that includes all required safety equipment and ventilation infrastructure.
- 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.
- Build a parametric filament storage clip in OpenSCAD: a clip that holds the free end of a filament spool. Parameters: filament diameter, clip width.
- Research OSHA’s published guidance on VOC exposure in 3D printing environments. Summarize the key recommendations.
- Compare the Safety Data Sheets (SDS) for PLA and ABS filament from two manufacturers. Document differences in recommended exposure limits and PPE.
- 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.
- Create a safety poster covering the five most important 3D printing safety rules, organized using the Hierarchy of Controls framework.
- Write a one-page risk assessment for a new FDM printer being added to a classroom.
- Design and describe a parametric filament moisture indicator holder: a small box that holds a humidity indicator card inside a resealable filament storage bag.
- Build a “print monitoring log” template: a paper form with columns for time, nozzle temperature, bed temperature, layer number, visual observations, and action taken.
- Research the difference between particle emissions and VOC emissions from FDM printing. Which is considered more hazardous at typical classroom distances from the printer?
- 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.
- 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
| Hazard | Temperature / Condition | Response |
|---|---|---|
| Hot nozzle | 190–260°C | Do not touch; wait for < 50°C |
| Hot bed | 50–110°C | Do not touch; allow full cool-down |
| Fumes (ABS/PETG) | At operating temp | Ventilate; use enclosure with filtration |
| Electrical (power supply) | 120V / 240V mains | Never open while plugged in |
| Tangled filament | Any | Clear 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
| Property | PLA | PETG | TPU (Flex) | ABS |
|---|---|---|---|---|
| Difficulty | Easiest | Moderate | Hard | Very Hard |
| Nozzle temp | 190–220°C | 230–250°C | 220–240°C | 230–250°C |
| Bed temp | 50–60°C | 70–85°C | 30–60°C | 90–110°C |
| Enclosure needed? | No | No | No | Yes |
| Rigidity | High | Medium | None — flexible | High |
| Impact resistance | Low (brittle) | Medium | Very high | Medium |
| Heat resistance | Low (~60°C) | Medium (~80°C) | Medium | High (~100°C) |
| Flexibility | None | Slight | Rubber-like | None |
| Moisture sensitivity | Low | Medium | High | Medium |
| Fume concern | Lowest | Low | Moderate | High |
| Bed adhesion | Easy | Use glue stick on PEI | Easy | Requires enclosure + glue |
| Print speed | Normal | Normal | Slow (20–30 mm/s) | Normal |
| Stringing tendency | Low | Medium–High | High | Low |
| Approximate cost | $15–25/kg | $15–30/kg | $20–40/kg | $15–25/kg |
| Recommended for beginners? | ✅ Yes | After PLA | After 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
| Filament | PrusaSlicer Profile | Key Changes from PLA Default |
|---|---|---|
| PLA | Generic PLA | Baseline — no changes needed |
| PETG | Generic PETG | Higher temps; slower cooling; glue stick on PEI bed |
| TPU | Generic Flex | Reduce speed to 20–30 mm/s; reduce retraction |
| ABS | Generic ABS | Higher 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.
| Filament | Moisture Sensitivity | Storage Recommendation |
|---|---|---|
| PLA | Low | Sealed bag with desiccant when not in use |
| PETG | Medium | Sealed bag with desiccant; dry before use if stored open for weeks |
| TPU | High | Always store sealed; dry in oven at 65°C for 4–6 hours if moisture-absorbed |
| ABS | Medium | Sealed 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
| Property | PLA | PETG | ABS | TPU |
|---|---|---|---|---|
| Nozzle temp (°C) | 200–220 | 235–250 | 240–260 | 220–240 |
| Bed temp (°C) | 20–60 | 70–90 | 100–110 | 20–60 |
| Strength | Moderate | High | Very High | Low (flexible) |
| Flexibility | None | Slight | Slight | High |
| Ease of printing | Very Easy | Easy | Hard | Moderate |
| Cost ($/kg) | $15–25 | $20–30 | $18–28 | $30–50 |
| Print speed | 40–60 mm/s | 30–50 mm/s | 20–40 mm/s | 10–30 mm/s |
| Bed adhesion | Easy | Moderate | Requires prep | Easy |
| UV resistance | Low | Moderate | High | Low |
| Chemical resistance | No | Moderate | Yes | No |
Heat Resistance After Printing
This is one of the most common reasons to choose a material other than PLA.
| Material | Safe to use up to | Softens at | Notes |
|---|---|---|---|
| PLA | ~50–60°C | ~60–70°C | Not suitable for car interiors or items near heat sources |
| PETG | ~80–100°C | ~100–110°C | Handles warm environments well |
| ABS | ~90–110°C | ~110–120°C | Good heat resistance; most demanding to print |
| TPU | ~60–80°C | ~80–100°C | Limited heat resistance despite flex durability |
Chemical Resistance
| Material | Water | Alcohol | Acetone | Oils | Acids |
|---|---|---|---|---|---|
| PLA | Low | Low | Dissolves | Low | Low |
| PETG | High | Moderate | Moderate | High | Moderate |
| ABS | High | Moderate | Dissolves | High | Moderate |
| TPU | Moderate | Low | Low | Moderate | Low |
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 Printing | Approximate Strength |
|---|---|
| 0–24 hours | 70–80% of final strength |
| 24–48 hours | 90–95% of final strength |
| 48–72 hours | ~99% of final strength |
| 7+ days | Maximum strength |
Do not stress-test functional parts immediately after printing. Allow at least 24 hours before load testing.
Storage Conditions
| Factor | Recommended Range |
|---|---|
| Storage temperature | 15–25°C |
| Relative humidity | 30–50% |
| Light exposure | Away from direct sunlight |
| Container | Sealed with desiccant packets |
Quick Material Selection Guide
| Question | Answer |
|---|---|
| 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
| Field | Value |
|---|---|
| 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
| Date | Type | Description | Time Spent | Issues Found | Resolution | By |
|---|---|---|---|---|---|---|
Types: Routine / Repair / Calibration / Cleaning / Part replacement
Issue Tracking Log
| Date | Symptom | Diagnosis | Action Taken | Status | Notes |
|---|---|---|---|---|---|
Statuses: Open / In progress / Resolved / Monitoring
Parts Replacement Record
| Date | Part Replaced | Reason | Supplier | Cost | Notes |
|---|---|---|---|---|---|
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.
| Filament | Brand | Nozzle Temp | Bed Temp | Speed | Success Rate | Notes |
|---|---|---|---|---|---|---|
| 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
| Month | Print Success Rate | Common Issues | Overall 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:
- Opening File Explorer (click)
- Navigating folders (click, click, click)
- Right-clicking a file (click)
- Selecting “Copy” (click)
- Navigating to destination (click, click)
- Right-clicking (click)
- 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:
| Task | Command Prompt | PowerShell | Git Bash |
|---|---|---|---|
| Show current location | cd | pwd | pwd |
| List files | dir /B | ls -n | ls |
| Go to folder | cd Documents | cd Documents | cd Documents |
| Go up one level | cd .. | cd .. | cd .. |
| Go home | cd %USERPROFILE% | cd ~ | cd ~ |
| Create folder | mkdir Projects | mkdir Projects | mkdir Projects |
| Create file | echo text > file.txt | echo "text" > file.txt | echo "text" > file.txt |
| Copy file | copy old.txt new.txt | Copy-Item old.txt new.txt | cp old.txt new.txt |
| Move file | move old.txt folder/ | Move-Item old.txt folder/ | mv old.txt folder/ |
| Delete file | del file.txt | Remove-Item file.txt | rm file.txt |
| List with filter | dir /B *.txt | ls *.txt | ls *.txt |
| Save output to file | dir > list.txt | ls > list.txt | ls > list.txt |
| Page through output | dir | more | ls | more | ls | less |
| Search in files | findstr "text" file.txt | Select-String "text" file.txt | grep "text" file.txt |
| Show file contents | type file.txt | cat file.txt or Get-Content | cat file.txt |
| Create script | .bat files | .ps1 files | .sh files |
| Run script | script.bat | .\script.ps1 | ./script.sh |
Feature Comparison Table
| Feature | CMD | PowerShell | Git Bash |
|---|---|---|---|
| Simplicity | Easiest | Moderate | Hardest |
| Beginner-Friendly | Best | Good | Challenging |
| Power/Capability | Basic | Excellent | Excellent |
| Screen Reader Compatible | Perfect | Perfect | Perfect |
| Linux/macOS Skills | Windows-only | Some overlap | Full overlap |
| 3D Printing Automation | Adequate | Excellent | Adequate |
| Learning Curve | Gentle | Moderate | Steep |
| Community Support | Moderate | Excellent | Excellent |
| Windows Integration | Perfect | Perfect | Good |
| Installation Difficulty | Built-in | Built-in | Requires 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
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
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
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
- 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
- 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
- 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:
- Opening File Explorer (click)
- Navigating folders (click, click, click)
- Right-clicking a file (click)
- Selecting “Copy” (click)
- Navigating to destination (click, click)
- Right-clicking (click)
- 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:
| Task | Command Prompt | PowerShell | Git Bash |
|---|---|---|---|
| Show current location | cd | pwd | pwd |
| List files | dir /B | ls -n | ls |
| Go to folder | cd Documents | cd Documents | cd Documents |
| Go up one level | cd .. | cd .. | cd .. |
| Go home | cd %USERPROFILE% | cd ~ | cd ~ |
| Create folder | mkdir Projects | mkdir Projects | mkdir Projects |
| Create file | echo text > file.txt | echo "text" > file.txt | echo "text" > file.txt |
| Copy file | copy old.txt new.txt | Copy-Item old.txt new.txt | cp old.txt new.txt |
| Move file | move old.txt folder/ | Move-Item old.txt folder/ | mv old.txt folder/ |
| Delete file | del file.txt | Remove-Item file.txt | rm file.txt |
| List with filter | dir /B *.txt | ls *.txt | ls *.txt |
| Save output to file | dir > list.txt | ls > list.txt | ls > list.txt |
| Page through output | dir | more | ls | more | ls | less |
| Search in files | findstr "text" file.txt | Select-String "text" file.txt | grep "text" file.txt |
| Show file contents | type file.txt | cat file.txt or Get-Content | cat file.txt |
| Create script | .bat files | .ps1 files | .sh files |
| Run script | script.bat | .\script.ps1 | ./script.sh |
Feature Comparison Table
| Feature | CMD | PowerShell | Git Bash |
|---|---|---|---|
| Simplicity | Easiest | Moderate | Hardest |
| Beginner-Friendly | Best | Good | Challenging |
| Power/Capability | Basic | Excellent | Excellent |
| Screen Reader Compatible | Perfect | Perfect | Perfect |
| Linux/macOS Skills | Windows-only | Some overlap | Full overlap |
| 3D Printing Automation | Adequate | Excellent | Adequate |
| Learning Curve | Gentle | Moderate | Steep |
| Community Support | Moderate | Excellent | Excellent |
| Windows Integration | Perfect | Perfect | Good |
| Installation Difficulty | Built-in | Built-in | Requires 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
| Section | Title | Time |
|---|---|---|
| Screen Reader Accessibility Guide | NVDA, JAWS, and terminal accessibility reference | 1.5 hrs |
| Lesson Pre: Your First Terminal | Opening PowerShell, first commands, basic navigation | 2–2.5 hrs |
| Lesson 0: Getting Started | Paths, shortcuts, tab completion | 1.5 hrs |
| Lesson 1: Navigation | Moving around the file system confidently | 2–2.5 hrs |
| Lesson 2: File and Folder Manipulation | Create, copy, move, delete files and folders | 2.5–3 hrs |
| Lesson 3: Input, Output, and Piping | Chain commands together, redirect output | 2.5–3 hrs |
| Lesson 4: Environment Variables and Aliases | Automate settings, create shortcuts | 2–2.5 hrs |
| Lesson 5: Filling in the Gaps | Profiles, history, debugging | 2–2.5 hrs |
| Lesson 6: Advanced Techniques | Scripts, functions, loops, professional workflows | 4–4.5 hrs |
| Unit Exam | Comprehensive assessment — Lessons 0 through 6 | 60–90 min |
Part 2 — Windows Command Prompt (CMD)
| Section | Title | Time |
|---|---|---|
| Screen Reader Accessibility Guide | NVDA, JAWS, Narrator, and SuperNova reference for CMD | 1.5 hrs |
| Lesson Pre: Your First Terminal | Opening CMD, first commands, basic navigation | 1.5–2 hrs |
| Lesson 0: Getting Started | Paths, shortcuts, tab completion | 1.5 hrs |
| Lesson 1: Navigation | Moving around the file system confidently | 2–2.5 hrs |
| Lesson 2: File and Folder Manipulation | Create, copy, move, delete files and folders | 2.5–3 hrs |
| Lesson 3: Input, Output, and Piping | Redirect output, chain commands with pipes | 2.5–3 hrs |
| Lesson 4: Environment Variables and Aliases | Automate settings, create doskey shortcuts | 2–2.5 hrs |
| Lesson 5: Filling in the Gaps | Autorun scripts, history, debugging | 2–2.5 hrs |
| Lesson 6: Advanced Techniques | Batch scripts, subroutines, loops, professional workflows | 4–4.5 hrs |
| Unit Exam | Comprehensive assessment — Lessons 0 through 6 | 60–90 min |
Part 3 — Git Bash
| Section | Title | Time |
|---|---|---|
| Screen Reader Accessibility Guide | NVDA, JAWS, Narrator, and SuperNova reference for Git Bash | 1–1.5 hrs |
| Tutorial: Git Bash Quick Start | Prompt orientation, core commands, path concepts | 30–45 min |
| Lesson Pre: Your First Terminal | Installing Git Bash, opening it, first commands | 1.5–2 hrs |
| Lesson 0: Getting Started | Paths, ~, ./, ../, tab completion | 20–30 min |
| Lesson 1: Navigation | pwd, cd, ls and flags, wildcards | 1 class period |
| Lesson 2: File and Folder Manipulation | touch, mkdir, cp, mv, rm, rmdir | 30–45 min |
| Lesson 3: Input, Output, and Piping | echo, cat, >, >>, |, clip, grep | 1 class period |
| Lesson 4: Environment Variables and Aliases | $VARNAME, PATH, which, alias, .bashrc | 30–45 min |
| Lesson 5: Filling in the Gaps | history, Ctrl+R, .bashrc, ./ | 30–45 min |
| Lesson 6: Advanced Techniques | Shell scripts, functions, loops, professional workflows | 4–4.5 hrs |
| Unit Exam | Comprehensive assessment — Lessons 0 through 6 | 60–90 min |
Quick Jump — By Lesson Across All Three Shells
| Lesson | PowerShell | CMD | Git Bash |
|---|---|---|---|
| Accessibility Guide | PS | CMD | Git Bash |
| Lesson Pre | PS | CMD | Git Bash |
| Lesson 0: Getting Started | PS | CMD | Git Bash |
| Lesson 1: Navigation | PS | CMD | Git Bash |
| Lesson 2: File & Folder Manipulation | PS | CMD | Git Bash |
| Lesson 3: Input, Output & Piping | PS | CMD | Git Bash |
| Lesson 4: Environment Variables | PS | CMD | Git Bash |
| Lesson 5: Filling in the Gaps | PS | CMD | Git Bash |
| Lesson 6: Advanced Techniques | PS | CMD | Git Bash |
| Unit Exam | PS | CMD | Git 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
| Section | Title | Estimated Time |
|---|---|---|
| Screen Reader Accessibility Guide | NVDA, JAWS, and terminal accessibility reference | 1.5 hours |
| Lesson Pre: Your First Terminal | Opening PowerShell, first commands, basic navigation | 2–2.5 hours |
| Lesson 0: Getting Started | Paths, shortcuts, tab completion | 1.5 hours |
| Lesson 1: Navigation | Moving around the file system confidently | 2–2.5 hours |
| Lesson 2: File and Folder Manipulation | Create, copy, move, delete files and folders | 2.5–3 hours |
| Lesson 3: Input, Output, and Piping | Chain commands together, redirect output | 2.5–3 hours |
| Lesson 4: Environment Variables and Aliases | Automate settings, create shortcuts | 2–2.5 hours |
| Lesson 5: Filling in the Gaps | Profiles, history, debugging | 2–2.5 hours |
| Lesson 6: Advanced Techniques | Scripts, functions, loops, professional workflows | 4–4.5 hours |
| Unit Exam | Comprehensive assessment — Lessons 0 through 6 | 60–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
- Getting Started with Screen Readers
- NVDA-Specific Tips
- JAWS-Specific Tips
- General Terminal Accessibility
- Working with Long Output
- Keyboard Shortcuts Reference
- 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
- Start your screen reader before opening PowerShell.
- Open PowerShell and listen for the window title and prompt.
- 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
| Command | What It Does |
|---|---|
| NVDA+Home | Read the current line (your command or output) |
| NVDA+Down Arrow | Read from cursor to end of screen |
| NVDA+Up Arrow | Read from top to cursor |
| NVDA+Page Down | Read next page |
| NVDA+Page Up | Read previous page |
| NVDA+F7 | Open 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
| Command | What It Does |
|---|---|
| Insert+Down Arrow | Read line by line downward |
| Insert+Up Arrow | Read line by line upward |
| Insert+Page Down | Read next page of text |
| Insert+Page Up | Read previous page of text |
Example: Reading Long Output
- Redirect:
Get-ChildItem -Name > list.txt - Open Notepad:
notepad list.txt - 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>
Navigation Sequence
- Screen reader announces the title
- Then it announces the prompt line
- 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
| Key | Action |
|---|---|
| Up Arrow | Show previous command |
| Down Arrow | Show next command |
| Tab | Auto-complete file/folder names |
| Home | Jump to start of line |
| End | Jump to end of line |
| Ctrl+C | Stop command |
| Enter | Run command |
Troubleshooting
Problem: “I Can’t Hear the Output”
- Redirect to file and open in Notepad.
- Use End to jump to the end of text.
Problem: “Tab Completion Isn’t Working”
- Type some characters before Tab.
Problem: “Command Not Found”
- Use
Get-Command programnameto check availability.
Pro Tips
- Use
Get-ChildItem -Namefor one-per-line listings. - Use
Out-File -FilePath list.txtto capture output with encoding options.
Recommended Workflow
Set-Location(orcd) to the project folderGet-ChildItem -Nameto list files- Redirect large output to files and open in Notepad
Additional Resources
- NVDA Documentation: https://www.nvaccess.org/documentation/
- JAWS Documentation: https://www.freedomscientific.com/support/
- PowerShell Documentation: https://docs.microsoft.com/powershell
- NVDA Documentation: https://www.nvaccess.org/documentation/
- JAWS Documentation: https://www.freedomscientific.com/support/
- Dolphin SuperNova: https://yourdolphin.com/supernova/
- Windows Narrator: https://support.microsoft.com/narrator
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)
- Press the Windows key alone
- You should hear “Search”
- Type:
PowerShell - You’ll hear search results appear
- Press Enter to open the first result (Windows PowerShell)
- PowerShell will open in a new window
Method 2: Using the Start Menu
- Press Windows key + X (opens the Quick Link menu)
- Look for “Windows PowerShell” or “Terminal”
- Press Enter
Method 3: From File Explorer
- Open File Explorer
- Navigate to any folder
- In the menu bar, select “File” -> “Open Windows PowerShell here”
- 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” indicatorC:\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:
- Run
pwdto confirm you’re in Documents - Run
ls -nto see what files are in Documents - Try going back:
cd ..(the..means “go up one level”) - Run
pwdagain to confirm - 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"
Navigating Tab Completion
One of the most powerful screen reader tricks is Tab completion:
How it works:
- Type the first few letters of a folder or file name
- Press Tab
- PowerShell automatically completes the rest
Example:
- You’re in
C:\Users\YourName> - Type:
cd Doc - Press Tab
- PowerShell auto-completes it to:
cd Documents - Press Enter to go there
With a screen reader:
- As you type
Doc, your screen reader announces each letter - When you press Tab, PowerShell types the rest and your screen reader announces the full command
- 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:
echosends text to the screen (or file)"Hello, PowerShell!"is the text>redirects it to a file calledhello.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 Combination | What It Does |
|---|---|
| Up Arrow | Shows your previous command (press again to go further back) |
| Down Arrow | Shows your next command (if you went back) |
| Tab | Auto-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
-
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
-
Reviewing Text:
- Use NVDA+Shift+Page Up to review text above
JAWS Users
-
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
-
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:
- Make sure your cursor is at the prompt (try pressing End or Ctrl+End)
- Use Up Arrow to go back to your previous command and review it
- Try redirecting to a file:
command > output.txtthen open the file - 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
- Open PowerShell
- Run
pwdand note your location - Run
ls -nand listen to what’s there - Try
cd Documentsor another folder - Run
pwdto confirm your new location - Run
ls -nin this new location
Goal: You should be comfortable knowing where you are and what’s around you
Exercise 2: Using Tab Completion
- In your home directory, type
cd D(just the letter D) - Press Tab
- PowerShell should auto-complete to a folder starting with D
- Repeat with other folder names
- Try typing a longer name:
cd Downand Tab toDownloads
Goal: Tab completion should feel natural
Exercise 3: Creating and Viewing Files
- Create a file:
echo "Test content" > test.txt - View it:
cat test.txt - Create another:
echo "Line 2" > another.txt - List both:
ls -n
Goal: You understand create, view, and list operations
Exercise 4: Going Up Levels
- Navigate into several folders:
cd Documents, thencd folder1, etc. - From deep inside, use
cd ..multiple times to go back up - After each
cd .., runpwdto confirm your location
Goal: You understand relative navigation with ..
Exercise 5: Redirecting Output
- Create a list:
ls -n > directory_list.txt - Open it:
notepad.exe directory_list.txt - Read it with your screen reader
- Close Notepad
- 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:
- What does
pwddo? - What does
ls -ndo? - Why do we use
-nwithls? - What path are you in right now?
- How do you navigate to a new folder?
- How do you go up one level?
- What’s the Tab key for?
- What does
echo "text" > file.txtdo? - How do you read a file back?
- 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.txtto save output to a file, then open it withnotepad.exe file.txtfor 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
- Microsoft PowerShell Docs: https://docs.microsoft.com/powershell/
- NVDA Screen Reader: https://www.nvaccess.org/
- JAWS Screen Reader: https://www.freedomscientific.com/products/software/jaws/
- Windows Terminal Accessibility: https://docs.microsoft.com/windows/terminal/
Troubleshooting
| Issue | Solution |
|---|---|
| PowerShell won’t open | Try searching Windows, or right-click a folder and select “Open PowerShell here” |
| Can’t hear the output | Try redirecting to a file: command > output.txt |
| Tab completion not working | Make sure you typed at least one character before pressing Tab |
| Command not found | Make sure you spelled it correctly; try Get-Command to see available commands |
| Stuck in a command | Press 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
- Open PowerShell and note the prompt (it includes the current path).
- Run
pwdand say or note the printed path. - Use
ls -nto list names in your home directory. - Practice
cd Documents,cd ../andcd ~until comfortable. - Try tab-completion: type
cd ~/Dand 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
- What is a path?
- What does
~mean? - How do you autocomplete a path?
- How do you go up one directory?
- What command lists only names (
lsflag)? - True or False: On Windows, PowerShell uses backslashes (
\) in paths, but forward slashes (/) are also accepted. - Explain the difference between an absolute path and a relative path.
- If you are in
C:\Users\YourName\Documentsand you typecd ../, where do you end up? - What happens when you press Tab while typing a folder name in PowerShell?
- Describe a practical reason why understanding paths is important for a 3D printing workflow.
- What does
./mean in a path, and when would you use it? - If a folder path contains spaces (e.g.,
Program Files), how do you navigate to it withcd? - Explain what the prompt
PS C:\Users\YourName>tells you about your current state. - How would you navigate to your home directory from any location using a single command?
- What is the advantage of using relative paths (like
../) versus absolute paths in automation scripts?
Extension Problems
- Create a nested folder and practice
cdinto it by typing partial names and using Tab. - Use
ls -n -afto list only files in a folder. - Save
pwdoutput to a file and open it in Notepad. - Try
cdinto a folder whose name contains spaces; observe how quotes are handled. - Create a short note file and open it from PowerShell.
- Build a folder structure that mirrors your project organization; navigate to each level and document the path.
- Create a script that prints your current path and the total number of files in it; run it from different locations.
- Investigate the special paths (e.g.,
$HOME,$PSScriptRoot); write down what each contains and when you’d use them. - Compare absolute vs. relative paths by navigating to the same folder using each method; explain which is easier for automation.
- Create a PowerShell function that changes to a frequently-used folder and lists its contents in one command; test it from different starting locations.
- Navigate to three different locations and at each one note the prompt, the path from
pwd, and verify you understand what each shows. - Create a complex folder tree (at least 5 levels deep) and navigate it using only relative paths; verify your location at each step.
- Document all shortcuts you know (
~,./,../,$HOME) and demonstrate each one works as expected. - Write a guide for a peer on how to understand the PowerShell prompt and path notation without using GUI file explorer.
- Create a troubleshooting flowchart: if someone says “I don’t know where I am,” what commands do you give them to find out?
References
- Microsoft. (2024). PowerShell scripting overview and documentation. https://learn.microsoft.com/powershell/scripting/overview
- Microsoft. (2024). Filesystem navigation in PowerShell. https://learn.microsoft.com/powershell/scripting/learn/shell/navigate-the-filesystem
- Microsoft. (2024). Accessibility features in PowerShell ISE. https://learn.microsoft.com/powershell/scripting/windows-powershell/ise/accessibility-in-windows-powershell-ise
Helpful Resources
- PowerShell Basics - Microsoft Learn
- Filesystem Navigation Guide
- Understanding Path Notation
- Tab Completion Reference
- Accessibility in PowerShell ISE
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
pwdto print your current location - Use
cdto 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
| Command | What It Does |
|---|---|
pwd | Print Working Directory - shows where you are |
cd path | Change Directory - move to a new location |
ls | List - shows files and folders in current location |
ls -n | List names only (screen reader friendly) |
ls -n -af | List names of files only |
ls -n -ad | List names of directories only |
ls *.extension | List 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
- Run
pwdand confirm your location - Move to
Documents:cd Documents - Confirm you moved:
pwd - List files and folders:
ls -n - List only files:
ls -n -af - Go back up:
cd .. - 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
- What does
pwdshow? - How do you list directories only with
ls? - What wildcard matches any number of characters?
- How do you list files with the
.scadextension? - Give an example of an absolute path and a relative path.
- True or False: The
*wildcard matches exactly one character. - Explain the difference between
ls -nandls -n -ad. - Write a command that would list all
.txtfiles in your Documents folder using a wildcard. - How would you search for files containing “part” in their name across multiple files?
- Describe a practical scenario where using wildcards saves time in a 3D printing workflow.
- What happens when you use
ls -n part?.scadversusls -n part*.scad? - How would you navigate to a folder whose name contains both spaces and special characters?
- If you’re in
/Documents/Projects/3Dand you want to go to/Documents/Resources, what command would you use? - Write a command sequence that navigates to the Downloads folder, lists only files, then returns to home.
- Explain the purpose of using
ls -n -afspecifically in a screen reader context.
Extension Problems
- Write a one-line script that lists
.scadfiles and saves toscad_list.txt. - Use
ls -n ~/Documents | moreto page through long listings. - Combine
lswithSelect-Stringto search for a filename pattern. - Create a shortcut alias in the session for a long path and test it.
- Practice tab-completion in a directory with many similarly named files.
- Build a PowerShell script that recursively lists all
.scadand.stlfiles in a directory tree; save the results to a file. - Compare the output of
ls,Get-ChildItem, andgcito understand PowerShell aliasing; document what each command does. - Create a filtering command that displays only files modified in the last 7 days; test it on your documents folder.
- Write a non-visual guide to PowerShell navigation; include descriptions of common patterns and how to verify directory contents audibly.
- Develop a navigation workflow for a typical 3D printing project: move between CAD, slicing, and print-log folders efficiently; document the commands.
- Create a complex wildcard search: find all files in a folder and subfolders that match multiple patterns (e.g.,
*_v1.* OR *_final.*). - Build a script that navigates through a folder tree, counts files at each level, and reports the structure.
- Document the output differences between
ls -n,ls -n -af,ls -n -ad, andGet-ChildItem; explain when to use each. - Create a navigation “cheat sheet” as a PowerShell script that prints common paths and how to navigate to them.
- Design a project folder structure on your computer, document each path, then create a script that validates all folders exist.
References
- Microsoft. (2024). Get-ChildItem cmdlet reference. https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-childitem
- Microsoft. (2024). PowerShell wildcards and filtering. https://learn.microsoft.com/powershell/scripting/learn/shell/using-wildcards
- Microsoft. (2024). Navigation best practices in PowerShell. https://learn.microsoft.com/powershell/scripting/learn/shell/navigate-the-filesystem
Helpful Resources
- Get-ChildItem Cmdlet Reference
- PowerShell Wildcards and Filtering
- Navigation Best Practices
- Relative and Absolute Paths
- Screen Reader Tips for PowerShell
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, andrmdirsafely - Understand when operations are permanent and how to confirm results
Materials
- PowerShell
- Small practice folder for exercises
Step-by-step Tasks
- Create a practice directory:
mkdir ~/Documents/PS_Practiceandcdinto it. - Create two files:
ni file1.txtandni file2.txt. - Copy
file1.txttofile1_backup.txtwithcpand confirm withls -n. - Rename
file2.txttonotes.txtusingmvand confirm. - Delete
file1.txtwithrmand 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
- How do you create an empty file from PowerShell?
- What command copies a file?
- How do you rename a file?
- What does
rm -rdo? - Why is
rmpotentially dangerous? - True or False:
cprequires the-rflag to copy both files and folders. - Explain the difference between
rmandrmdir. - If you delete a file with
rm, can you recover it from PowerShell? - Write a command that would copy an entire folder and all its contents to a new location.
- Describe a practical safety check you would perform before running
rm -ron a folder.
Caution
By default,
cpsilently overwrites an existing file at the destination with no warning. Usecp -i(interactive) to get a confirmation prompt before overwriting, especially when working with important files.
- What happens if you
cpa file to a destination where a file with the same name already exists? How would you handle this safely? - Compare
mv old_name.txt new_name.txtvsmv old_name.txt ~/Documents/new_name.txt. What is the key difference? - Design a workflow to safely delete 50 files matching the pattern
*.bakfrom a folder containing 500 files. What commands and verifications would you use? - Explain how you could back up all
.scadfiles from a project folder into a timestamped backup folder in one command. - 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
- Create a folder tree and copy it to a new location with
cp -r. - Write a one-line command that creates three files named
a b cand lists them. - Move a file into a new folder and confirm the move.
- Use wildcards to delete files matching a pattern in a safe test folder.
- Export a listing of the practice folder to
practice_listing.txt. - Create a backup script that copies all
.scadfiles from your project folder to a backup folder with timestamp naming. - Build a safe deletion workflow: list files matching a pattern, verify count, then delete with confirmation; document the steps.
- Write a PowerShell script that organizes files by extension into subfolders; test it on a sample folder tree.
- Create a file operation audit trail: log all copy, move, and delete operations to a text file for review.
- Develop a project template generator: a script that creates a standard folder structure for a new 3D printing project with essential subfolders.
- Implement a file conflict handler: write a script that handles cases where
cpwould overwrite an existing file by renaming the existing file with a timestamp before copying. - Create a batch rename operation: use a script to rename all files in a folder from
old_prefix_*tonew_prefix_*; test with actual files and verify the results. - 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.
- 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. - 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
- Microsoft. (2024). New-Item cmdlet reference. https://learn.microsoft.com/powershell/module/microsoft.powershell.management/new-item
- Microsoft. (2024). Copy-Item and Move-Item cmdlets. https://learn.microsoft.com/powershell/module/microsoft.powershell.management/copy-item
- Microsoft. (2024). File system operations guide. https://learn.microsoft.com/powershell/scripting/learn/shell/manipulating-items
Helpful Resources
- New-Item Cmdlet Reference
- Copy-Item and Move-Item
- Remove-Item Cmdlet Reference
- File System Operations Guide
- Safe Deletion Practices
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
echoto print text to the screen - Use
catto 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
| Command | What It Does |
|---|---|
echo "text" | Print text to the screen |
cat filename | Print the contents of a file |
> filename | Redirect output into a file (overwrites) |
>> filename | Append output to a file (adds to end) |
| | Pipe - send output from one command to the next |
clip | Copy piped input to the Windows clipboard |
notepad.exe filename | Open 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
- Create
practice.txtwith three lines usingechoand>/>>. - Read the file with
cat practice.txt. - Pipe the file into
Select-Stringto search for a word. - Copy the file contents to clipboard with
cat practice.txt | clip. - Redirect
ls -nintolist.txtand open it in Notepad. Checkpoints
- After step 3 you should be able to find a keyword using piping.
Quiz - Lesson PS.3
- What is the difference between
>and>>? - What does the pipe
|do? - How do you copy output to the clipboard?
- How would you page through long output?
- How do you suppress output to nowhere?
- True or False: The pipe operator
|connects the output of one command to the input of another. - Explain why redirecting output to a file is useful for screen reader users.
- Write a command that would search for the word “sphere” in all
.scadfiles in a directory. - How would you count the number of lines in a file using PowerShell piping?
- Describe a practical scenario in 3D printing where you would pipe or redirect command output.
- What would be the difference in output between
echo "test" > file.txt(run twice) vsecho "test" >> file.txt(run twice)? Show the expected file contents. - Design a three-step piping chain: read a file, filter for specific content, and save the results; explain what each pipe does.
- You have a 500-line
.scadfile and need to find all instances ofsphere()and count them. Write the command. - Explain how
clipis particularly valuable for screen reader users when working with file paths or long output strings. - Describe how you would use pipes and redirection to create a timestamped backup report of all
.stlfiles in a 3D printing project folder.
Extension Problems
- Use piping to count lines in a file (hint:
Select-String -Pattern '.' | Measure-Object). - Save a long
ls -noutput and search it withSelect-String. - Chain multiple pipes to filter and then save results.
- Practice copying different command outputs to clipboard and pasting.
- Create a small script that generates a report (counts of files by extension).
- Build a data processing pipeline: read a CSV file, filter rows, and export results; document each step.
- Write a script that pipes directory listing to Count occurrences of each file extension; create a summary report.
- Create a log analysis command: read a log file, filter for errors, and save matching lines to a separate error log.
- Design a piping workflow for 3D printing file management: find
.stlfiles, extract their sizes, and generate a report. - Develop a reusable piping function library: create functions for common filtering, sorting, and reporting patterns; test each function with different inputs.
- Build a complex filter pipeline: read a
.scadfile, extract lines containing specific geometry commands, count each type, and output a summary to both screen and file. - Create an interactive piping tool: build a script that accepts user input for a search term, pipes through multiple filters, and displays paginated results.
- Develop a performance analysis tool: use piping to combine file listing, metadata extraction, and statistical reporting; export results to a dated report file.
- Implement a comprehensive error-handling pipeline: read output, catch errors, log them separately, and generate a summary of successes vs failures.
- 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
- Microsoft. (2024). Out-File cmdlet for redirection. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/out-file
- Microsoft. (2024). Select-String piping reference. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-string
- Microsoft. (2024). PowerShell pipeline concepts. https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pipeline
Helpful Resources
- Using Out-File for Redirection
- Piping and Select-String
- Get-Content Cmdlet Reference
- Measure-Object for Counting
- PowerShell Pipeline Concept
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
- Show your username and home path with
echo $env:USERNAMEandecho $env:USERPROFILE. - Inspect
echo $env:PATHand identify whetheropenscadorcodewould be found. - Run
Get-Command openscadand note the result. - Create a temporary alias:
Set-Alias -Name preview -Value openscadand testpreview myfile.scad. - 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
- How do you print an environment variable?
- What is the purpose of
PATH? - How do you check whether
openscadis available? - How do you create a temporary alias?
- Where would you make an alias permanent?
- True or False: Environment variables are case-sensitive on all platforms.
- Explain why having a program in your PATH is useful compared to always using its full file path.
- Write a command that would create an alias called
slicerfor the OpenSCAD executable. - What file would you edit to make an alias persist across PowerShell sessions?
- Describe a practical benefit of using the
$env:TEMPdirectory for temporary files in a 3D printing workflow. - You have a custom script at
C:\Scripts\backup_models.ps1that you want to run from anywhere asbackup-now. What steps would you take to make this work? - Explain the difference between setting an environment variable in the current session vs. adding it to your profile for permanence.
- 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.
- If a program is not found by
Get-Command, what are the possible reasons, and how would you troubleshoot? - 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
- Add a folder to PATH for a test program (describe steps; do not change system PATH without admin).
- Create a short profile snippet that sets two aliases and test re-opening PowerShell.
- Use
Get-Commandto list the path for several common programs. - Explore
$env:TEMPand create a file there. - Save a copy of your current PATH to a text file and examine it in your editor.
- Create a PowerShell profile script that loads custom aliases and environment variables for your 3D printing workflow; test it in a new session.
- Build a “project profile” that sets environment variables for CAD, slicing, and print directories; switch between profiles for different projects.
- Write a script that audits your current environment variables and creates a summary report of what’s set and why.
- Design a custom alias system for common 3D printing commands; document the aliases and their purposes.
- Create a profile migration guide: document how to export and import your PowerShell profile across machines for consistent workflows.
- 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.
- 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.
- 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.
- 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.
- 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
- Microsoft. (2024). Environment variables in PowerShell. https://learn.microsoft.com/powershell/scripting/learn/shell/using-environment-variables
- Microsoft. (2024). Set-Alias cmdlet reference. https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/set-alias
- Microsoft. (2024). Creating and using PowerShell profiles. https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_profiles
Helpful Resources
- Environment Variables in PowerShell
- Understanding the PATH Variable
- Set-Alias Cmdlet Reference
- Creating a PowerShell Profile
- Get-Command for Locating Programs
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
- Run several simple commands (e.g.,
pwd,ls -n,echo hi) then runhistoryto view them. - Use
Invoke-History <n>to re-run a previous command (replace<n>with a history number). - Practice aborting a long-running command with
Ctrl + C(for example,ping 8.8.8.8). - Open your profile:
notepad.exe $PROFILE; if it doesn’t exist, create it:ni $PROFILE -Force. - 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
- How do you view the command history?
- Which key combination aborts a running command?
- What does
echo $PROFILEshow? - How does the
&operator help run executables? - What is one strategy if terminal output stops being announced by your screen reader?
- True or False: Using
Ctrl+Cpermanently deletes any files created by the command you abort. - Explain the difference between
historyandGet-Historyin PowerShell. - If you place code in your profile but it doesn’t take effect after opening a new PowerShell window, what should you verify?
- Write a command that would run a program at the path
C:\Program Files\OpenSCAD\openscad.exedirectly. - Describe a practical workflow scenario where having keyboard shortcuts (aliases) in your profile would save time.
- Explain how to re-run the 5th command from your history, and what would happen if that command had file operations (creates/deletes).
- Design a profile initialization strategy that separates utilities for different projects; explain how you would switch between them.
- 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.
- 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?
- 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
- Add an alias and an environment variable change to your profile and document the behavior after reopening PowerShell.
- Create a short script that automates creating a project folder and an initial .scad file.
- Experiment with running OpenSCAD by full path using
&and by placing it in PATH; compare results. - Practice redirecting
Get-Helpoutput to a file and reading it in Notepad for screen reader clarity. - Document three screen reader troubleshooting steps you used and when they helped.
- Build a comprehensive PowerShell profile that includes aliases, environment variables, and helper functions for your 3D printing workflow.
- Create a script that troubleshoots common PowerShell issues (module loading, permission errors, command not found); test at least three scenarios.
- Write a PowerShell function that coordinates multiple tasks: creates a project folder, starts OpenSCAD, and opens slicing software.
- Design a screen-reader accessibility guide for PowerShell: document commands, outputs, and accessible navigation patterns.
- Develop an advanced PowerShell workflow: implement error handling, logging, and confirmation prompts for risky operations.
- 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.
- Build a profile debugger: create a script that compares two PowerShell sessions’ environment states (variables, aliases, functions) to identify what loaded/failed to load.
- 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.
- 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.
- 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
- Microsoft. (2024). PowerShell history and recall functionality. https://learn.microsoft.com/powershell/scripting/learn/shell/using-history
- Microsoft. (2024). Understanding and creating PowerShell profiles. https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_profiles
- Microsoft. (2024). The call operator (&) for running executables. https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_operators#call-operator-
Helpful Resources
- PowerShell History and Recall
- Understanding Profiles
- Invoke-History Cmdlet Reference
- The Call Operator (&)
- Screen Reader Tips and Tricks
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
.ps1script, PowerShell’s security is blocking unsigned scripts. Use-Scope Processto 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$mypathwith 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 functionparam([string]$path)= the function accepts a parameter called$path- Inside the function, use
$pathlike 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 variableforeach ($file in $scadFiles)= for each file, do this:Write-Output "=== File: $file ==="= announce which filecat $file= show contentsWrite-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:
- List them all
- Check how many there are
- 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 lookls $scadFolder -Filter *.scad -Name= find .scad files, show names onlyforeach= process each fileJoin-Path= combine folder and filename into full pathTest-Path= check if file existsif= do different things based on condition
Running the Script
- Save as
batch-process.ps1 - Edit
$scadFolderto match your real folder - 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 truereturn= 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:
- Create file:
notepad.exe hello.ps1 - Type:
Write-Output "Hello from my first PowerShell script!" pwd ls -n - 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:
- Create file:
notepad.exe smart-listing.ps1 - Type:
$targetFolder = "C:\Users\YourName\Documents" Write-Output "Listing contents of: $targetFolder" ls -n $targetFolder - Edit
$targetFolderto a real folder on your computer - Run:
.\smart-listing.ps1
Checkpoint: You should see listing of that specific folder.
Exercise 3: Function
Goal: Create a reusable function
Steps:
- Create file:
notepad.exe navigate.ps1 - 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" - 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:
- Create file:
notepad.exe repeat.ps1 - Type:
Write-Output "Demonstrating a loop:" for ($i = 1; $i -le 5; $i++) { Write-Output "Iteration $i: Hello!" } Write-Output "Loop complete!" - 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:
- Create a folder:
mkdir C:\Users\YourName\Documents\TestFiles - 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 - Create script:
notepad.exe report.ps1 - 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 ===" - Run:
.\report.ps1
Checkpoint: Should show report of all files in the test folder.
Quiz — Lesson 6
- What is a PowerShell script?
- What file extension do PowerShell scripts use?
- What is a variable and how do you create one?
- What is a function and why would you use one?
- How do you run a script?
- What is a loop and what does
foreachdo? - What does
Test-Pathdo? - How do you handle errors in a script?
- When would you use
Try-Catch? - What technique makes script output readable for screen readers?
Extension Problems
- Auto-Backup Script: Create a script that copies all files from one folder to another, announcing progress
- File Counter: Write a function that counts files by extension (.txt, .scad, .stl, etc.)
- Folder Cleaner: Script that deletes files older than 30 days (with user confirmation)
- Project Template: Function that creates a complete project folder structure with all needed files
- Batch Rename: Script that renames all files in a folder according to a pattern
- Log Generator: Create a script that records what it does to a log file for later review
- Scheduled Task: Set up a script to run automatically every day at a specific time
- File Verifier: Check that all SCAD files in a folder have corresponding STL exports
- Report Generator: Create a summary report of all projects in a folder
- 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
- Microsoft PowerShell Scripting Guide: https://docs.microsoft.com/powershell/scripting/
- Function Documentation: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_functions_advanced
- Error Handling: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_error_handling
- Loops: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_foreach
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:
- Understanding of file system navigation and path concepts
- Proficiency with file and folder manipulation commands
- Ability to redirect and pipe command output
- Knowledge of environment variables and aliases
- Screen-reader accessibility best practices in terminal environments
- 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.
-
What is the primary purpose of the
PATHenvironment 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
-
Which command prints your current working directory?
- A)
ls -n - B)
cd - C)
pwd - D)
whoami
- A)
-
What does the
~symbol represent in PowerShell paths?- A) The root directory
- B) The current directory
- C) The parent directory
- D) The home directory
-
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
- A)
-
Which command creates a new empty file?
- A)
mkdir filename - B)
ni filename - C)
touch filename - D)
echo filename
- A)
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.
-
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
- A)
-
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
-
Which command copies a file?
- A)
mv - B)
rm - C)
cp - D)
cd
- A)
-
How do you rename a file from
oldname.txttonewname.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
- A)
-
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
-
Which key combination allows you to autocomplete a path in PowerShell?
- A)
Ctrl + A - B)
Ctrl + E - C)
Tab - D)
Space
- A)
-
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
- A)
-
What does
Get-Command openscaddo?- 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
-
Which wildcard matches any single character?
- A)
* - B)
? - C)
% - D)
#
- A)
-
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
-
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
- A)
-
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
-
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
- A) Press
-
What command shows the history of previously run commands?
- A)
history - B)
Get-History - C)
Show-History - D) Both A and B
- A)
-
How do you permanently set an alias so it persists across PowerShell sessions?
- A) Use
Set-Aliasin the terminal every time - B) Add the
Set-Aliasline to your PowerShell profile - C) Use the Windows Control Panel
- D) Aliases cannot be made permanent
- A) Use
Part B: Short Answer Questions (10 questions)
Answer each question in one to two sentences. Each question is worth 2 points.
-
Explain the difference between absolute and relative paths. Give one example of each.
-
Why is
ls -npreferred overlsfor screen reader users? Describe what flag you would use to list only files. -
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_folderpermanently deletes the folder and everything inside it — all files, all subdirectories — with no confirmation and no undo. Always verify the path withls -1first and consider making a backup withcp -rbefore running recursive deletions.
-
Describe what would happen if you ran
rm -r ~/Documents/my_folderand why this command should be used carefully. -
How would you search for all files with a
.scadextension in your current directory? Write the command. -
Explain what happens when you pipe the output of
ls -nintoclip. What would you do next? -
What is an environment variable, and give one example of how you might use it in PowerShell.
-
If a program is not in your
PATH, what two methods could you use to run it from PowerShell? -
Describe how you would open a file in Notepad and also add a line to it from PowerShell.
-
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
-
Create a folder structure
~/Documents/PowerShell_Assessment/Projectsusing a single command. Capture thels -noutput showing the creation. -
Create five files named
project_1.scad,project_2.scad,project_3.txt,notes_1.txt, andnotes_2.txtinside theProjectsfolder. Use wildcards to list only.scadfiles, then capture the output. -
Copy the entire
Projectsfolder toProjects_Backupusingcp -r. Capture thels -noutput showing both folders exist. -
Move (rename)
project_1.scadtoproject_1_final.scad. Capture thels -noutput showing the renamed file. -
Delete
notes_1.txtandnotes_2.txtusing a singlermcommand with wildcards. Capture the finalls -noutput.
Tasks 6-10: Advanced Operations and Scripting
-
Create a file called
my_data.txtwith at least four lines usingechoand>>. Then read it withcat my_data.txtand capture the output. -
Use
Select-Stringto search for a keyword (e.g., “project”) inmy_data.txtand pipe the results toclip. Paste the results into Notepad and capture a screenshot. -
List all files in the
Projectsfolder and redirect the output toprojects_list.txt. Open it in Notepad and capture a screenshot of the file. -
Create a temporary alias called
mylsthat runsls -n, test it, and capture the output. Then explain what would be required to make it permanent. -
Run
Get-Help Get-ChildItemand redirect the output tohelp_output.txt. Open the file in Notepad and capture a screenshot showing at least the first page of help content.
Grading Rubric
| Section | Questions | Points Each | Total |
|---|---|---|---|
| Multiple Choice | 20 | 1 | 20 |
| Short Answer | 10 | 2 | 20 |
| Hands-On Tasks | 10 | 3 | 30 |
| Total | 40 | - | 70 |
Passing Score: 49 points (70%)
Helpful Resources for Review
- PowerShell Command Reference
- Navigation and File System
- Using Pipes and Filtering
- Profile and Aliases
- Screen Reader Accessibility Tips
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
| Section | Title | Estimated Time |
|---|---|---|
| Screen Reader Accessibility Guide | NVDA, JAWS, Narrator, and SuperNova reference for CMD | 1.5 hours |
| Lesson Pre: Your First Terminal | Opening CMD, first commands, basic navigation | 1.5–2 hours |
| Lesson 0: Getting Started | Paths, shortcuts, tab completion | 1.5 hours |
| Lesson 1: Navigation | Moving around the file system confidently | 2–2.5 hours |
| Lesson 2: File and Folder Manipulation | Create, copy, move, delete files and folders | 2.5–3 hours |
| Lesson 3: Input, Output, and Piping | Redirect output, chain commands with pipes | 2.5–3 hours |
| Lesson 4: Environment Variables and Aliases | Automate settings, create doskey shortcuts | 2–2.5 hours |
| Lesson 5: Filling in the Gaps | Autorun scripts, history, debugging | 2–2.5 hours |
| Lesson 6: Advanced Techniques | Batch scripts, subroutines, loops, professional workflows | 4–4.5 hours |
| Unit Exam | Comprehensive assessment — Lessons 0 through 6 | 60–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 /Bto confirm exactly what you are about to delete before runningdelorrmdir /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 baredir. The/B(bare) flag outputs one name per line, which screen readers can follow reliably. Barediroutputs 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 withnotepad.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
- Getting Started with Screen Readers
- NVDA-Specific Tips
- JAWS-Specific Tips
- General Terminal Accessibility
- Working with Long Output
- Keyboard Shortcuts Reference
- 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
- Start your screen reader before opening CMD.
- Open Command Prompt and listen for the window title and prompt.
- 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
| Command | What It Does |
|---|---|
| NVDA+Home | Read the current line (your command or output) |
| NVDA+Down Arrow | Read from cursor to end of screen |
| NVDA+Up Arrow | Read from top to cursor |
| NVDA+Page Down | Read next page |
| NVDA+Page Up | Read previous page |
| NVDA+F7 | Open 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
| Command | What It Does |
|---|---|
| Insert+Down Arrow | Read line by line downward |
| Insert+Up Arrow | Read line by line upward |
| Insert+Page Down | Read next page of text |
| Insert+Page Up | Read previous page of text |
Example: Reading Long Output
- Redirect:
dir /b > list.txt - Open Notepad:
notepad list.txt - 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>
Navigation Sequence
- Screen reader announces the title
- Then it announces the prompt line
- 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
| Key | Action |
|---|---|
| Up Arrow | Show previous command |
| Down Arrow | Show next command |
| Tab | Auto-complete file/folder names |
| Home | Jump to start of line |
| End | Jump to end of line |
| Ctrl+C | Stop command |
| Enter | Run command |
Troubleshooting
Problem: “I Can’t Hear the Output”
- Redirect to file and open in Notepad.
- Use End to jump to the end of text.
Problem: “Tab Completion Isn’t Working”
- Type at least one character before Tab.
Problem: “Command Not Found”
- Use
where programnameto find installed programs.
Pro Tips
- Use
dir /bfor one-per-line listings. - Create a personal notes file and open it in Notepad for quick reference.
Recommended Workflow
cdto the project folderdir /bto list files- Redirect large output to files and open in Notepad
Additional Resources
- NVDA Documentation: https://www.nvaccess.org/documentation/
- JAWS Documentation: https://www.freedomscientific.com/support/
- Windows CMD Reference: https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands
- NVDA Documentation: https://www.nvaccess.org/documentation/
- JAWS Documentation: https://www.freedomscientific.com/support/
- Dolphin SuperNova: https://yourdolphin.com/supernova/
- Windows Narrator: https://support.microsoft.com/narrator
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)
- Press the Windows key alone.
- Type:
cmd - You will hear search results appear.
- Press Enter to open the first result (Command Prompt).
Method 2: Using the Run Dialog
- Press Windows key + R (opens the Run dialog).
- Type:
cmd - Press Enter.
Method 3: From the Start Menu
- Press the Windows key.
- Navigate to Windows System or Windows Tools (depending on your Windows version).
- 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:
- Run
cdto confirm you are in Documents. - Run
dir /Bto see what is there. - Go back up:
cd ..(the..means “go up one level”). - Run
cdagain to confirm. - 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:
- Type the first few letters of a folder or file name.
- Press Tab.
- Command Prompt automatically completes the rest.
Example:
- You are at
C:\Users\YourName> - Type:
cd Doc - Press Tab
- Command Prompt completes it to:
cd Documents - 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
echooutputs text.>redirects it to a file calledhello.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 Combination | What It Does |
|---|---|
| Up Arrow | Shows your previous command (press again for earlier commands) |
| Down Arrow | Shows a more recent command in history |
| Tab | Auto-completes folder and file names |
| Ctrl+C | Stops a running command |
| cls | Clears the screen (type this and press Enter) |
| Enter | Runs the command you have typed |
| Home | Moves cursor to start of command line |
| End | Moves cursor to end of command line |
Screen Reader-Specific Tips
NVDA Users
NVDA is available free from https://www.nvaccess.org/
- After running a command, press NVDA+Home (Insert+Home or CapsLock+Home) to read the current line.
- To read all output, press NVDA+Down Arrow to read from the cursor to the end of the screen.
- 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.
- If output scrolled past, redirect to a file:
command > output.txt, thennotepad.exe output.txt. - 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/
- After running a command, press Insert+Up Arrow to re-read the current line.
- To read all output, press Insert+Ctrl+Down to read to the end of the screen.
- To move through output line by line, press Insert+Down Arrow repeatedly.
- If output is too long, redirect to a file:
command > output.txt, thennotepad.exe output.txt. - 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.
- After running a command, press Narrator+D (CapsLock+D or Insert+D) to read the current line.
- To read all output from here, press Narrator+R to read from the cursor position.
- To move through output, use Narrator+Up/Down Arrow in scan mode (press Narrator+Space to toggle scan mode on).
- For long outputs, always redirect to a file:
command > output.txt, thennotepad.exe output.txt. Notepad is more comfortable for Narrator users than reading directly from the terminal. - 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/
- After running a command, press CapsLock+L to read the current line.
- To read all output, press CapsLock+Numpad Plus (say all from current position).
- To move through output, press CapsLock+Numpad 8 (up) and CapsLock+Numpad 2 (down) to move line by line through the review buffer.
- For long outputs, redirect to a file:
command > output.txt, thennotepad.exe output.txt. - 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:
- 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.
- Press End to make sure your cursor is at the prompt.
- Redirect to a file:
command > output.txt, thennotepad.exe output.txt. This always works with all screen readers. - 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
- Open Command Prompt.
- Run
cdand note your location. - Run
dir /Band listen to the listing. - Type
cd Documentsand press Enter. - Run
cdto confirm your new location. - Run
dir /Bin this new location.
Goal: You know where you are and what is around you.
Exercise 2: Using Tab Completion
- In your home directory, type
cd D(just those two characters). - Press Tab.
- Command Prompt should auto-complete to a folder starting with D.
- Repeat with other folder names.
- Try
cd Downand Tab toDownloads.
Goal: Tab completion feels natural.
Exercise 3: Creating and Viewing Files
- Create a file:
echo Test content > test.txt - View it:
type test.txt - Create another:
echo Line 2 > another.txt - List both:
dir /B *.txt
Goal: You understand create, view, and list operations.
Exercise 4: Going Up Levels
- Navigate into several folders:
cd Documents, thencd folder1, etc. - From inside, run
cd ..multiple times to come back up. - After each
cd .., runcdto confirm your location.
Goal: You are comfortable with relative navigation using ..
Exercise 5: Redirecting Output
- Create a listing:
dir /B > directorylist.txt - Open it:
notepad.exe directorylist.txt - Read it with your screen reader.
- 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:
- What does
cddo with no arguments? - What does
dir /Bdo? - Why do we use
/Bwithdir? - What is your current path right now?
- How do you navigate to a new folder?
- How do you go up one level?
- What is the Tab key for?
- What does
echo text > file.txtdo? - How do you read a file back in the terminal?
- 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
| Issue | Solution |
|---|---|
| Command Prompt won’t open | Press Windows+R, type cmd, press Enter |
| Cannot hear the output | Redirect to a file: command > output.txt, then notepad.exe output.txt |
| Tab completion not working | Type at least one character before pressing Tab |
| Command not found | Check spelling; try help for a list of available commands |
| Stuck in a command | Press Ctrl+C to stop it |
| JAWS stops working mid-session | If using JAWS demo: restart computer, demo sessions last ~40 minutes |
Resources
- NVDA: https://www.nvaccess.org/
- JAWS: https://www.freedomscientific.com/products/software/jaws/
- Windows Narrator guide: https://support.microsoft.com/narrator
- Dolphin SuperNova: https://yourdolphin.com/supernova/
- Windows CMD Reference: https://example.com
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
- Open Command Prompt and note the prompt (it includes the current path).
- Run
cdand say or note the printed path. - Use
dir /Bto list names in your home directory. - Practice
cd Documents,cd ..andcd \until comfortable. - Try tab-completion: type
cd Dand 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
- What is a path?
- What does
..mean? - How do you autocomplete a path?
- How do you go up one directory?
- What command lists only names (
dirflag)? - True or False: On Windows, CMD uses backslashes (
\) in paths, but forward slashes (/) are also accepted in some contexts. - Explain the difference between an absolute path and a relative path.
- If you are in
C:\Users\YourName\Documentsand you typecd .., where do you end up? - What happens when you press Tab while typing a folder name in Command Prompt?
- Describe a practical reason why understanding paths is important for a 3D printing workflow.
- What does
C:\mean in a path, and when would you use it? - If a folder path contains spaces (e.g.,
Program Files), how do you navigate to it withcd? - Explain what the prompt
C:\Users\YourName>tells you about your current state. - How would you navigate to your home directory from any location using a single command?
- What is the advantage of using relative paths (like
..) versus absolute paths in automation scripts?
Extension Problems
- Create a nested folder and practice
cdinto it by typing partial names and using Tab. - Use
dir /B /A:Fto list only files in a folder. - Save
cdoutput (the path) to a file and open it in Notepad. - Try
cdinto a folder whose name contains spaces; observe how quotes are handled. - Create a short note file and open it from Command Prompt.
- Build a folder structure that mirrors your project organization; navigate to each level and document the path.
- Use
echo %cd%to print your current path and save it to a file. - Investigate special paths (e.g.,
%USERPROFILE%,%TEMP%); write down what each contains and when you’d use them. - Compare absolute vs. relative paths by navigating to the same folder using each method; explain which is easier for automation.
- Create a batch file that changes to a frequently-used folder and lists its contents in one command; test it from different starting locations.
- Navigate to three different locations and at each one note the prompt, the path from
cd, and verify you understand what each shows. - Create a complex folder tree (at least 5 levels deep) and navigate it using only relative paths; verify your location at each step.
- Document all path shortcuts you know (
C:\,..,.) and demonstrate each one works as expected. - Write a guide for a peer on how to understand the Command Prompt and path notation without using GUI file explorer.
- Create a troubleshooting flowchart: if someone says “I don’t know where I am,” what commands do you give them to find out?
References
- Microsoft. (2024). Command line reference. https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/
- Microsoft. (2024). Using the cd command. https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cd_1
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 rootUsers— First folderYourName— Your user folderDocuments— Documents folder3DPrinting— 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)
- Type the first few characters of a folder name.
- Press Tab.
- 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
- After each
cdcommand, runcdalone to confirm location. Press NVDA+Home (Insert+Home) to read the current line. - Press NVDA+Down Arrow to read through
dir /Boutput. - For long listings:
dir /B > listing.txt, thennotepad.exe listing.txt.
JAWS Users
- After each
cdcommand, press Insert+Up Arrow to re-read the current line. - Press Insert+Down Arrow repeatedly to read output line by line.
- For long listings:
dir /B > listing.txt, thennotepad.exe listing.txt.
Windows Narrator Users
- After each
cdcommand, press Narrator+D (CapsLock+D) to read the current line. - Press Narrator+R to read output from the current position.
- 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
- After each
cdcommand, press CapsLock+L to read the current line. - Press CapsLock+Numpad Plus (say all) to read all output from the current position.
- For long listings:
dir /B > listing.txt, thennotepad.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
cd %USERPROFILE%- Run
cdto see location. dir /Bcd Documents- Run
cdto confirm. dir /B
Exercise 2: Using Tab Completion
cd %USERPROFILE%- Type
cd Docthen press Tab. - Press Enter.
- Run
cdto confirm.
Exercise 3: Navigating Up
- Navigate several levels deep.
- Run
cdto see full path. - Use
cd ..to go up one level at a time. - Run
cdafter each step.
Exercise 4: Absolute Path Navigation
- Navigate deep (3+ levels).
- Run
cd %USERPROFILE%to jump home. - Run
cdto 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:
- What is the difference between
cd Documentsandcd \? - What does
cd ..do? - How do you go to your home folder from anywhere?
- What is an absolute path? Give an example.
- What is a relative path? Give an example.
- How do you confirm your current location?
- What does Tab completion do?
- How would you navigate 3 levels deep, then back home?
- What is the difference between
.and..? - If you are lost, what command should you run first?
Extension Problems
- Create a folder with spaces in the name (e.g.,
My Projects) and navigate to it using quotes. - Use Tab completion to navigate 5+ levels deep without typing full names.
- Create a script that saves
cdoutput at each level to a log file. - Navigate to the same destination using both absolute and relative paths from different starting locations.
- Build a complex folder tree (5+ levels) and navigate using only relative paths.
- Document the full paths to your 5 most-used folders.
- Create folders named
01Folder,02Folder, etc. and practice Tab completion through them. - Navigate to a folder, save the path with
cd > mypath.txt, navigate away, then return using the saved path. - Challenge: navigate to a destination using only relative paths without running
cdto check at each step. - 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 /Bto 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
/Ecopies all subdirectories including empty ones./Itreats 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
/Qflag suppresses the confirmation prompt —del /Qdeletes immediately and silently. Only use/Qin 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
deldoes not send files to the Recycle Bin. Deleted files are permanently gone with no undo. Always verify the target withdir /Bbefore 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 /Qpermanently deletes a folder and all its contents with no confirmation and no undo. Always verify the exact folder name withdir /Bfirst — one wrong character can delete the wrong folder entirely.
Safe File Operations
Caution
Check, then delete. Never run
delorrmdirwithout first runningdir /Bto confirm exactly what you’re about to remove. Wildcards likedel *.txtwill 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
mkdir practice-sessioncd practice-sessionmkdir files documents modelsdir /B /A:D
Goal: Create organized folder structures confidently.
Exercise 2: Create and Copy Files
echo Hello World > test.txttype test.txtcopy test.txt test-backup.txtdir /B *.txttype test-backup.txt
Goal: Create and copy files without errors.
Exercise 3: Safe Deletion Practice
echo content > file1.txtecho content > file2.txtecho content > file3.txtdir /B *.txt(confirm all three exist)del file1.txt(delete just one)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
- Create three files:
echo a > doc1.txt,echo b > doc2.txt,echo c > doc3.txt dir /B *.txtmkdir archivecopy *.txt archive\cd archivedir /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, ordeloperation, always verify withdir /Bto 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
- How do you create a folder?
- How do you copy a file?
- How do you rename a file?
- How do you delete a file safely (checking first)?
- What does
*match in a wildcard pattern? - What does
?match in a wildcard pattern? - How would you copy all .scad files to a backup folder?
- What should you always do before deleting?
- How do you delete a folder and all its contents?
- Why is it important to create a backup before editing?
Extension Problems
- Create a nested folder structure (5+ levels) using a single
mkdircommand with backslashes. - Create 10 files and organize them into subfolders using
movewith wildcards. - Create a date-based backup strategy: copy all files to a folder named with today’s date.
- Use wildcards to select specific file types and copy them to separate organized folders.
- 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
echoto print text to the screen - Use
typeto 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
| Command | What It Does |
|---|---|
echo text | Print text to the screen |
type filename | Print the contents of a file |
> filename | Redirect output into a file (overwrites) |
>> filename | Append output to a file (adds to end) |
| | Pipe - send output from one command to the next |
clip | Copy piped input to the Windows clipboard |
notepad filename | Open 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
- Create
practice.txtwith three lines usingechoand>/>>. - Read the file with
type practice.txt. - Pipe the file into
findto search for a word. - Copy the file contents to clipboard with
type practice.txt | clip. - Redirect
dir /Bintolist.txtand open it in Notepad.
Checkpoints
- After step 3 you should be able to find a keyword using piping.
Quiz - Lesson CMD.3
- What is the difference between
>and>>? - What does the pipe
|do? - How do you copy output to the clipboard?
- How would you page through long output?
- How do you suppress output (send it nowhere)?
- True or False: The pipe operator
|connects the output of one command to the input of another. - Explain why redirecting output to a file is useful for screen reader users.
- Write a command that would search for the word “sphere” in all
.scadfiles in a directory. - How would you count the number of lines in a file using CMD piping?
- Describe a practical scenario in 3D printing where you would pipe or redirect command output.
- What would be the difference in output between
echo test > file.txt(run twice) vsecho test >> file.txt(run twice)? Show the expected file contents. - Design a three-step piping chain: read a file, filter for specific content, and save the results; explain what each pipe does.
- You have a 500-line
.scadfile and need to find all instances ofsphere()and count them. Write the command. - Explain how
clipis particularly valuable for screen reader users when working with file paths or long output strings. - Describe how you would use pipes and redirection to create a timestamped backup report of all
.stlfiles in a 3D printing project folder.
Extension Problems
- Use piping to count lines in a file (hint:
type file.txt | find /C /V ""). - Save a long
dir /Boutput and search it withfind. - Chain multiple pipes to filter and then save results.
- Practice copying different command outputs to clipboard and pasting.
- Create a small batch script that generates a report (counts of files by extension).
- Build a data processing pipeline: read a text file, filter rows, and export results; document each step.
- Write a batch script that pipes directory listing to count occurrences of each file extension; create a summary report.
- Create a log analysis command: read a log file, filter for errors, and save matching lines to a separate error log.
- Design a piping workflow for 3D printing file management: find
.stlfiles, extract their names, and generate a report. - Develop a reusable piping pattern library: create batch scripts for common filtering, sorting, and reporting patterns; test each with different inputs.
- Build a complex filter pipeline: read a
.scadfile, extract lines containing specific geometry commands, count each type, and output a summary to both screen and file. - Create an interactive filtering tool: build a batch script that accepts a search term, pipes through multiple filters, and displays paginated results.
- Develop a performance analysis tool: use piping to combine file listing, metadata extraction, and statistical reporting; export results to a dated report file.
- Implement a comprehensive error-handling pipeline: read output, catch errors, log them separately, and generate a summary of successes vs failures.
- 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
- Microsoft. (2024). Using redirection operators in CMD. https://example.com
- Microsoft. (2024). FIND command reference. https://example.com
- Microsoft. (2024). CMD pipeline concepts. https://example.com
Helpful Resources
- Using Redirection in CMD
- Piping and FIND
- TYPE Command Reference
- FINDSTR for Advanced Searching
- CMD Pipeline Concepts
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
doskeyand understand making them persistent via a startup script
Materials
- Command Prompt
Step-by-step Tasks
- Show your username and home path with
echo %USERNAME%andecho %USERPROFILE%. - Inspect
echo %PATH%and identify whetheropenscadorcodewould be found. - Run
where openscadand note the result. - Create a temporary alias:
doskey preview=openscad $*and testpreview myfile.scad. - 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
- How do you print an environment variable?
- What is the purpose of
PATH? - How do you check whether
openscadis available? - How do you create a temporary alias in CMD?
- Where would you make an alias permanent?
- True or False: Environment variable names in CMD are case-sensitive.
- Explain why having a program in your PATH is useful compared to always using its full file path.
- Write a command that would create a doskey alias called
slicerfor the OpenSCAD executable. - What file or technique would you use to make a doskey alias persist across CMD sessions?
- Describe a practical benefit of using the
%TEMP%directory for temporary files in a 3D printing workflow. - You have a custom batch script at
C:\Scripts\backup_models.batthat you want to run from anywhere asbackup-now. What steps would you take to make this work? - Explain the difference between setting an environment variable in the current session with
setvs. usingsetxfor permanence. - Design a strategy for managing multiple 3D printing projects, each with different tool paths and directories; show how to structure environment variables for each.
- If a program is not found by
where, what are the possible reasons, and how would you troubleshoot? - 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
- Add a folder to PATH for a test program (describe steps; do not change system PATH without admin).
- Create a short autorun snippet that sets two aliases and test re-opening CMD.
- Use
whereto list the path for several common programs. - Explore
%TEMP%and create a file there. - Save a copy of your current PATH to a text file and examine it in your editor.
- Create a CMD autorun script that loads custom aliases and environment variables for your 3D printing workflow; test it in a new session.
- Build a “project profile” batch script that sets environment variables for CAD, slicing, and print directories; switch between profiles for different projects.
- Write a batch script that audits your current environment variables and creates a summary report of what’s set and why.
- Design a custom alias system using doskey for common 3D printing commands; document the aliases and their purposes.
- Create a profile migration guide: document how to export and import your CMD aliases and variables across machines for consistent workflows.
- 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. - Build a comprehensive autorun framework: create separate
.batfiles for aliases, environment variables, and helper macros; have your main autorun load all of them. - 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.
- 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.
- 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
- Microsoft. (2024). Environment variables in CMD. https://example.com
- Microsoft. (2024). DOSKEY command reference. https://example.com
- Microsoft. (2024). WHERE command reference. https://example.com
Helpful Resources
- Environment Variables in CMD
- Understanding the PATH Variable
- DOSKEY Alias Reference
- WHERE Command for Locating Programs
- SETX for Permanent Variables
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
startor 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
- Run several simple commands (e.g.,
cd,dir /B,echo hi) then pressF7or rundoskey /historyto view them. - Use
F8to search back through history, or use the up-arrow to re-run a previous command. - Practice aborting a long-running command with
Ctrl + C(for example,ping 8.8.8.8). - Open your autorun script:
notepad.exe autorun.bat; if it doesn’t exist, create it withecho. > autorun.bat. - 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
- How do you view the command history in CMD?
- Which key combination aborts a running command?
- What does
echo %CMDCMDLINE%show? - How does the
startcommand help run executables? - What is one strategy if terminal output stops being announced by your screen reader?
- True or False: Using
Ctrl+Cpermanently deletes any files created by the command you abort. - Explain the difference between pressing
F7and runningdoskey /historyin CMD. - 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?
- Write a command that would run a program at the path
C:\Program Files\OpenSCAD\openscad.exedirectly. - Describe a practical workflow scenario where having keyboard shortcuts (doskey macros) in your autorun script would save time.
- Explain how to re-run the 5th command from your history using
F7and selection, and what would happen if that command had file operations (creates/deletes). - Design an autorun initialization strategy that separates utilities for different projects; explain how you would switch between them.
- 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?
- 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?
- 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
- Add a doskey macro and an environment variable change to your autorun script and document the behavior after reopening CMD.
- Create a short batch script that automates creating a project folder and an initial
.scadfile. - Experiment with running OpenSCAD by full path using
startand by placing it in PATH; compare results. - Practice redirecting
helpoutput to a file and reading it in Notepad for screen reader clarity. - Document three screen reader troubleshooting steps you used and when they helped.
- Build a comprehensive CMD autorun script that includes aliases, environment variables, and helper macros for your 3D printing workflow.
- Create a batch script that troubleshoots common CMD issues (missing commands, permission errors, command not found); test at least three scenarios.
- Write a batch script that coordinates multiple tasks: creates a project folder, starts OpenSCAD, and opens a notes file.
- Design a screen-reader accessibility guide for CMD: document commands, outputs, and accessible navigation patterns.
- Develop an advanced CMD workflow: implement error handling, logging, and confirmation prompts for risky operations.
- 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. - Build an autorun debugger: create a script that compares two CMD sessions’ environment states (variables, aliases, macros) to identify what loaded/failed to load.
- 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.
- 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.
- 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
- Microsoft. (2024). CMD history and recall functionality. https://example.com
- Microsoft. (2024). Using CMD autorun scripts. https://example.com
- Microsoft. (2024). The START command for running executables. https://example.com
Helpful Resources
- DOSKEY History and Recall
- CMD Autorun Scripts
- START Command Reference
- CMD History Navigation
- Screen Reader Tips for CMD
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:
:ListFoldermarks the start of the subroutine%~1is the first argument passed to the subroutinecall :ListFolder "path"calls the subroutine with a pathgoto :eofexits 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) doiterates over each.scadfile%%fis the loop variable (use%fin interactive CMD,%%fin 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%%iis the counter variable
Real-World Example - Batch Processing SCAD Files
Scenario
You have 10 OpenSCAD (.scad) files in a folder. You want to:
- List them all
- Check how many there are
- 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 lookfor %%f in (...\*.scad)= find all .scad filesif 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
-
Save as
batch-process.bat -
Edit
scadFolderto match your real folder -
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%holds0for success or non-zero for failure if %errorlevel% neq 0checks 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 :eofexits 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:
-
Create file:
notepad.exe hello.bat -
Type:
@echo off echo Hello from my first CMD batch script! cd dir /B -
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:
-
Create file:
notepad.exe smart-listing.bat -
Type:
@echo off set targetFolder=C:\Users\YourName\Documents echo Listing contents of: %targetFolder% dir /B "%targetFolder%" -
Edit
targetFolderto a real folder on your computer -
Run:
smart-listing.bat
Checkpoint: You should see listing of that specific folder.
Exercise 3: Subroutine
Goal: Create a reusable subroutine
Steps:
-
Create file:
notepad.exe navigate.bat -
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 -
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:
-
Create file:
notepad.exe repeat.bat -
Type:
@echo off echo Demonstrating a loop: for /L %%i in (1,1,5) do ( echo Iteration %%i: Hello! ) echo Loop complete! -
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:
-
Create a folder:
mkdir C:\Users\YourName\Documents\TestFiles -
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 -
Create script:
notepad.exe report.bat -
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 === -
Run:
report.bat
Checkpoint: Should show report of all files in the test folder.
Quiz - Lesson CMD.6
- What is a CMD batch script?
- What file extension do CMD batch scripts use?
- What is a variable in a batch script and how do you create one?
- What is a subroutine (
:label) and why would you use one? - How do you run a batch script?
- What is a
forloop and what doesfor %%f in (*.scad) dodo? - What does
if existdo? - How do you handle errors in a batch script?
- When would you use
if %errorlevel% neq 0? - What technique makes batch script output readable for screen readers?
Extension Problems
- Auto-Backup Script: Create a batch script that copies all files from one folder to another, announcing progress
- File Counter: Write a subroutine that counts files by extension (.txt, .scad, .stl, etc.)
- Folder Cleaner: Batch script that deletes files older than 30 days (with user confirmation)
- Project Template: Subroutine that creates a complete project folder structure with all needed files
- Batch Rename: Script that renames all files in a folder according to a pattern
- Log Generator: Create a script that records what it does to a log file for later review
- Scheduled Task: Set up a batch script to run automatically every day at a specific time
- File Verifier: Check that all SCAD files in a folder have corresponding STL exports
- Report Generator: Create a summary report of all projects in a folder
- 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
- Microsoft CMD Batch Scripting Guide: https://example.com
- FOR Loop Documentation: https://example.com
- IF Statement Reference: https://example.com
- SET Variable Reference: https://example.com
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:
- Understanding of file system navigation and path concepts
- Proficiency with file and folder manipulation commands
- Ability to redirect and pipe command output
- Knowledge of environment variables and aliases
- Screen-reader accessibility best practices in terminal environments
- 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.
-
What is the primary purpose of the
PATHenvironment 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
-
Which command shows your current working directory in CMD?
- A)
dir /B - B)
cd(with no arguments) - C)
pwd - D)
whoami
- A)
-
What does
%USERPROFILE%represent in CMD?- A) The root directory
- B) The current directory
- C) The parent directory
- D) Your home directory
-
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
- A)
-
Which command creates a new empty file in CMD?
- A)
mkdir filename - B)
echo. > filename - C)
touch filename - D)
new filename
- A)
-
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
- A)
-
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
-
Which command copies a file in CMD?
- A)
move - B)
del - C)
copy - D)
cd
- A)
-
How do you rename a file from
oldname.txttonewname.txtin 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
- A)
-
What is the purpose of
findin 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
-
Which key allows you to autocomplete a path in CMD?
- A)
Ctrl + A - B)
Ctrl + E - C)
Tab - D)
Space
- A)
-
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
- A)
-
What does
where openscaddo?- 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
-
Which wildcard matches any single character?
- A)
* - B)
? - C)
% - D)
#
- A)
-
What is the purpose of the
startcommand?- 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
-
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
- A)
-
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
-
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
- A) Press
-
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
- A)
-
How do you make an environment variable permanent in CMD (for all future sessions)?
- A) Use
setin the terminal every time - B) Use
setxto write it to the registry - C) Use the Windows Control Panel only
- D) Environment variables cannot be made permanent in CMD
- A) Use
Part B: Short Answer Questions (10 questions)
Answer each question in one to two sentences. Each question is worth 2 points.
-
Explain the difference between absolute and relative paths. Give one example of each.
-
Why is
dir /Bpreferred overdirfor screen reader users? Describe what flag you would add to list only files. -
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_folderpermanently deletes the folder and all its contents with no confirmation prompt and no undo. Always rundir /B C:\Documents\my_folderfirst to confirm what you’re about to destroy.
-
Describe what would happen if you ran
rmdir /S /Q C:\Documents\my_folderand why this command should be used carefully. -
How would you search for all files with a
.scadextension in your current directory? Write the command. -
Explain what happens when you pipe the output of
dir /Bintoclip. What would you do next? -
What is an environment variable, and give one example of how you might use it in CMD.
-
If a program is not in your
PATH, what two methods could you use to run it from CMD? -
Describe how you would open a file in Notepad and also add a line to it from CMD.
-
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
-
Create a folder structure
%USERPROFILE%\Documents\CMD_Assessment\Projectsusing a single command. Capture thedir /Boutput showing the creation. -
Create five files named
project_1.scad,project_2.scad,project_3.txt,notes_1.txt, andnotes_2.txtinside theProjectsfolder. Use wildcards to list only.scadfiles, then capture the output. -
Copy the entire
Projectsfolder toProjects_Backupusingxcopy /E /I. Capture thedir /Boutput showing both folders exist. -
Move (rename)
project_1.scadtoproject_1_final.scad. Capture thedir /Boutput showing the renamed file. -
Delete
notes_1.txtandnotes_2.txtusing a singledelcommand with wildcards. Capture the finaldir /Boutput.
Tasks 6-10: Advanced Operations and Scripting
-
Create a file called
my_data.txtwith at least four lines usingechoand>>. Then read it withtype my_data.txtand capture the output. -
Use
findto search for a keyword (e.g., “project”) inmy_data.txtand pipe the results toclip. Paste the results into Notepad and capture a screenshot. -
List all files in the
Projectsfolder and redirect the output toprojects_list.txt. Open it in Notepad and capture a screenshot of the file. -
Create a temporary
doskeyalias calledmydirthat runsdir /B, test it, and capture the output. Then explain what would be required to make it persistent. -
Run
help dirand redirect the output tohelp_output.txt. Open the file in Notepad and capture a screenshot showing at least the first page of help content.
Grading Rubric
| Section | Questions | Points Each | Total |
|---|---|---|---|
| Multiple Choice | 20 | 1 | 20 |
| Short Answer | 10 | 2 | 20 |
| Hands-On Tasks | 10 | 3 | 30 |
| Total | 40 | - | 70 |
Passing Score: 49 points (70%)
Helpful Resources for Review
- CMD Command Reference
- Navigation and File System
- Using Pipes and Filtering
- DOSKEY and Aliases
- Screen Reader Accessibility Tips
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
| Section | Title | Estimated Time |
|---|---|---|
| Screen Reader Accessibility Guide | NVDA, JAWS, Narrator, and SuperNova reference for Git Bash | 1–1.5 hours |
| Tutorial: Git Bash Quick Start | Prompt orientation, core commands, path concepts | 30–45 minutes |
| Lesson Pre: Your First Terminal | Installing Git Bash, opening it, first commands | 1.5–2 hours |
| Lesson 0: Getting Started | Paths, ~, ./, ../, tab completion | 20–30 minutes |
| Lesson 1: Navigation | pwd, cd, ls and flags, wildcards | 1 class period |
| Lesson 2: File and Folder Manipulation | touch, mkdir, cp, mv, rm, rmdir | 30–45 minutes |
| Lesson 3: Input, Output, and Piping | echo, cat, >, >>, ` | , clip, grep` |
| Lesson 4: Environment Variables and Aliases | $VARNAME, PATH, which, alias, .bashrc | 30–45 minutes |
| Lesson 5: Filling in the Gaps | history, Ctrl+R, Ctrl+C, .bashrc, ./ | 30–45 minutes |
| Lesson 6: Advanced Techniques | Shell scripts, functions, loops, professional workflows | 4–4.5 hours |
| Unit Exam | Comprehensive assessment — Lessons 0 through 6 | 60–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
rmare permanently gone immediately — no undo, no recovery. Always runls -1to confirm exactly what you’re about to delete before running anyrmcommand.
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 barels. The-1flag outputs one name per line, which screen readers can follow reliably. Barelsoutputs 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 withnotepad.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
- Getting Started with Screen Readers
- NVDA-Specific Tips
- JAWS-Specific Tips
- General Terminal Accessibility
- Working with Long Output
- Keyboard Shortcuts Reference
- 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:
| Feature | NVDA | JAWS |
|---|---|---|
| Cost | Free | Commercial (paid) |
| Installation | Simple | Complex but thorough |
| Git Bash Support | Excellent | Excellent |
| Learning Curve | Gentle | Steeper |
| Customization | Good | Extensive |
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
- Make sure your screen reader is running before opening Git Bash
- Open Git Bash and let your screen reader read the window title and prompt
- If you don’t hear anything, press Alt+Tab to cycle windows and find Git Bash
- 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
| Command | What It Does |
|---|---|
| NVDA+Home | Read the current line (your command or output) |
| NVDA+Down Arrow | Read from cursor to end of screen |
| NVDA+Up Arrow | Read from top to cursor |
| NVDA+Page Down | Read next page |
| NVDA+Page Up | Read previous page |
| NVDA+F7 | Open the Review Mode viewer (can scroll through text) |
| NVDA+Shift+Right Arrow | Read next word |
| NVDA+Shift+Down Arrow | Read entire screen |
| NVDA+End | Jump to end of line |
| NVDA+Home | Jump to start of line |
Example: Reading Long Output
Scenario: You ran ls and it listed 50 files.
Solution with NVDA:
- After the command finishes, press NVDA+Home to read the current line
- Press NVDA+Down Arrow repeatedly to read all output
- 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
| Command | What It Does |
|---|---|
| Insert+Down Arrow | Read line by line downward |
| Insert+Up Arrow | Read line by line upward |
| Insert+Page Down | Read next page of text |
| Insert+Page Up | Read previous page of text |
| Insert+End | Jump to end of text on screen |
| Insert+Home | Jump to start of text on screen |
| Insert+Ctrl+Down | Read to end of screen |
| Insert+Ctrl+Up | Read to beginning of screen |
| Insert+F3 | Open JAWS menu |
Example: Reading Long Output
Scenario: You ran ls > list.txt and saved output to a file.
Solution with JAWS:
- Open the file:
notepad list.txt - In Notepad, press Insert+Ctrl+Down to hear all content
- 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:
- Title bar: Window name (e.g., “MINGW64:/c/Users/YourName”)
- Content area: Command history and output
- 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 usernameCOMPUTERNAME= your computer’s nameMINGW64= 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 ~.
Navigation Sequence
When you open Git Bash:
- Your screen reader announces the window title
- Then it announces the prompt line
- Anything before the prompt is previous output
- 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
grepto 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)
| Key | Action |
|---|---|
| Up Arrow | Show previous command |
| Down Arrow | Show next command |
| Tab | Auto-complete file/folder names |
| Shift+Tab | Cycle backward through completions |
| Home | Jump to start of line |
| End | Jump to end of line |
| Ctrl+A | Jump to start of line (alternate) |
| Ctrl+E | Jump to end of line (alternate) |
| Ctrl+C | Stop command |
| Ctrl+L | Clear screen |
| Enter | Run command |
| Ctrl+R | Search command history interactively |
Troubleshooting
Problem 1: “I Can’t Hear the Output After Running a Command”
- Redirect to file:
command > output.txtthennotepad output.txt - Press End or Ctrl+End to go to end of text
- Use Up Arrow to review previous command
Problem 2: “Tab Completion Isn’t Working”
- Need at least one character - type
cd Dthen Tab (not justcdthen Tab) - Check if item exists - use
lsfirst to see available items - Multiple matches - press Tab twice to list all options
Problem 3: “‘Command Not Found’ Error”
- Check spelling carefully
- Git Bash uses Unix commands: use
lsnotdir, usecatnottype - 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/Documentsor~/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”
- Press Up Arrow to show previous command
- Use arrow keys to move through it
- Edit the command
- 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
Recommended Workflow
For every new task:
- Know where you are:
pwd - See what’s around:
ls -1 - Plan your next step: Think before typing
- Run the command: Type and press Enter
- Check the output: Use screen reader or redirect to file
- Move forward: Next command or
cdto 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
- NVDA Documentation: https://www.nvaccess.org/documentation/
- JAWS Documentation: https://www.freedomscientific.com/support/
- Git for Windows (includes Git Bash): https://git-scm.com/
- Bash Manual: https://www.gnu.org/software/bash/manual/
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, andcdto 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 -1for 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(orCtrl+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)
- Open Git Bash; listen for the prompt and current path.
- Run
pwdto confirm your location. - Run
ls -1in your home directory and note the output. - Practice
cd Documents,cd ../, andcd ~to move between folders. - Create and open a file:
touch example.txt && notepad example.txt(orcode 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)
- What command prints your current directory?
- What does
~represent? - How do you list only names, one per line?
- How do you go up one directory level?
- How would you open
notes.txtin Notepad from Git Bash? - True or False: The pipe operator
|sends output to a file. - Explain why running a script requires
chmod +xfirst. - What is the difference between running a script with
./script.shversusbash script.sh? - Describe how you would handle a very long command output when using a screen reader.
- What does the
PATHenvironment variable do, and why is it important when running programs like OpenSCAD?
Extension Problems
- Create a folder
OpenSCADProjectsin Documents and verify its contents. - Create three files named
a.scad,b.scad,c.scadand list them with a wildcard. - Save
ls -1 ~/Documentsoutput todoclist.txtand open it. - Try tab-completion in a deeply nested folder and note behavior.
- Capture
pwdoutput into a file and open it:pwd > cwd.txt && notepad cwd.txt. - Build an automated setup script that creates a complete project directory structure, initializes placeholder files, and generates a README.
- Create a Git Bash cheat sheet for your most-used commands; organize by category (navigation, files, scripting, troubleshooting).
- Write a non-visual tutorial for Git Bash basics; use audio descriptions and keyboard-only navigation as the primary learning method.
- Develop a workflow automation script: combines multiple Git Bash concepts (folders, aliases, piping) to solve a real 3D printing task.
- Create a Git Bash proficiency self-assessment: list all concepts covered, provide test commands for each, and reflect on what you learned.
References
- Git for Windows. (2024). Git Bash. https://gitforwindows.org/
- GNU. (2024). Bash reference manual. https://www.gnu.org/software/bash/manual/bash.html
- The Linux Documentation Project. (2024). Bash Beginners Guide. https://tldp.org/LDP/Bash-Beginners-Guide/html/
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)
- Download from: https://git-scm.com/download/win
- Run the installer
- Accept defaults (all options work fine)
- Installation takes ~5 minutes
Opening Git Bash
Method 1: Search (Easiest)
- Press the Windows key alone
- You should hear “Search”
- Type:
Git Bash - You’ll hear search results appear
- Press Enter to open
Method 2: From File Explorer
- Open File Explorer
- Navigate to any folder
- Right-click on the folder
- Look for “Git Bash Here”
- 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 nameMINGW64= 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:
- Run
pwdto confirm you’re in Documents - Run
lsto see what files are in Documents - Try going back:
cd ..(the..means “go up one level”) - Run
pwdagain to confirm - 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:
echosends text to the screen (or file)"Hello, Git Bash!"is the text>redirects it to a file calledhello.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 Combination | What It Does |
|---|---|
| Up Arrow | Shows your previous command (press again to go further back) |
| Down Arrow | Shows your next command (if you went back) |
| Tab | Auto-completes folder/file names |
| Ctrl+C | Stops a running command |
| Ctrl+L | Clears the screen |
| Ctrl+A | Go to beginning of line |
| Ctrl+E | Go to end of line |
| Enter | Runs the command |
Screen reader tip: These all work perfectly with your screen reader. Try them!
Screen Reader-Specific Tips
NVDA Users
-
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
-
Reviewing Text:
- Use NVDA+Shift+Page Up to review text above
JAWS Users
-
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
-
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:
- Make sure your cursor is at the prompt (try pressing End or Ctrl+E)
- Use Up Arrow to go back to your previous command and review it
- Try redirecting to a file:
command > output.txtthen open the file - 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
- Open Git Bash
- Run
pwdand note your location - Run
lsand listen to what’s there - Try
cd Documentsor another folder - Run
pwdto confirm your new location - Run
lsin this new location
Goal: You should be comfortable knowing where you are and what’s around you
Exercise 2: Using Tab Completion
- In your home directory, type
cd D(just the letter D) - Press Tab
- Git Bash should auto-complete to a folder starting with D
- Repeat with other folder names
- Try typing a longer name:
cd Downand Tab
Goal: Tab completion should feel natural
Exercise 3: Creating and Viewing Files
- Create a file:
echo "Test content" > test.txt - View it:
cat test.txt - Create another:
echo "Line 2" > another.txt - List both:
ls *.txt
Goal: You understand create, view, and list operations
Exercise 4: Going Up Levels
- Navigate into several folders:
cd Documents, thencd folder1, etc. - From deep inside, use
cd ..multiple times to go back up - After each
cd .., runpwdto confirm your location
Goal: You understand relative navigation with ..
Exercise 5: Redirecting Output
- Create a list:
ls > directorylist.txt - Open it:
notepad.exe directorylist.txt - Read it with your screen reader
- Close Notepad
- 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:
- What does
pwddo? - What does
lsdo? - Why do we use
lsfor listings? - What path are you in right now?
- How do you navigate to a new folder?
- How do you go up one level?
- What’s the Tab key for?
- What does
echo "text" > file.txtdo? - How do you read a file back?
- 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
| Style | Example | Where Used |
|---|---|---|
| Windows | C:\Users\Name\Documents | CMD, PowerShell, Windows Explorer |
| Git Bash | /c/Users/Name/Documents | Git 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
- Git Bash Installation Guide: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
- Bash Basics: https://www.gnu.org/software/bash/manual/bash.html#Basic-Shell-Features
- NVDA Screen Reader: https://www.nvaccess.org/
- JAWS Screen Reader: https://www.freedomscientific.com/products/software/jaws/
Troubleshooting
| Issue | Solution |
|---|---|
| Git Bash won’t open | Make sure it’s installed; search for “Git Bash” in Start menu |
| Can’t hear the output | Try redirecting to a file: command > output.txt |
| Tab completion not working | Make sure you typed at least one character before pressing Tab |
| Command not found | Make sure you spelled it correctly; try man for available commands |
| Stuck in a command | Press 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
- Open Git Bash and note the prompt (it includes the current path).
- Run
pwdand say or note the printed path. - Use
lsto list names in your home directory. - Practice
cd Documents,cd ../andcd ~until comfortable. - Try tab-completion: type
cd ~/Dand 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
- What is a path?
- What does
~mean? - How do you autocomplete a path?
- How do you go up one directory?
- 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.
- True or False: Git Bash uses backslashes (
\) in paths like Windows CMD. - Explain the difference between an absolute path and a relative path.
- If you are in
/c/Users/YourName/Documentsand you typecd ../, where do you end up? - What happens when you press Tab while typing a folder name in Git Bash?
- Describe a practical reason why understanding paths is important for a 3D printing workflow.
- 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.
- If a folder path contains spaces (e.g.,
My Projects), how do you navigate to it withcd? - Explain what the prompt
YourName@COMPUTER MINGW64 ~/Documents $tells you about your current state. - How would you navigate to your home directory from any location using a single command?
- What is the advantage of using relative paths (like
../) versus absolute paths in automation scripts?
Extension Problems
- Create a nested folder and practice
cdinto it by typing partial names and using Tab. - Use
ls -lato list all files including hidden ones in a folder. - Save
pwdoutput to a file and open it in Notepad. - Try
cdinto a folder whose name contains spaces; observe how quotes are handled. - Create a short note file and open it from Git Bash.
- Build a folder structure that mirrors your project organization; navigate to each level and document the path.
- Create a script that prints your current path and the total number of files in it; run it from different locations.
- Investigate special paths (e.g.,
$HOME,$USER); write down what each contains and when you’d use them. - Compare absolute vs. relative paths by navigating to the same folder using each method; explain which is easier for automation.
- Create a bash function that changes to a frequently-used folder and lists its contents in one command; test it from different starting locations.
- Navigate to three different locations and at each one note the prompt, the path from
pwd, and verify you understand what each shows. - Create a complex folder tree (at least 5 levels deep) and navigate it using only relative paths; verify your location at each step.
- Document all shortcuts you know (
~,./,../,$HOME) and demonstrate each one works as expected. - Write a guide for a peer on how to understand the Git Bash prompt and path notation without using GUI file explorer.
- Create a troubleshooting flowchart: if someone says “I don’t know where I am,” what commands do you give them to find out?
References
- GNU. (2024). Bash Manual. https://example.com
- Git SCM. (2024). Git Bash documentation. https://example.com
- Linux Foundation. (2024). The Linux Command Line. https://example.com
Helpful Resources
- Bash Manual - Navigation
- Git Bash Basics
- Linux Path Guide
- Understanding Bash Prompts
- Tab Completion in Bash
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
pwdto print your current location - Use
cdto 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
| Command | What It Does |
|---|---|
pwd | Print Working Directory - shows where you are |
cd path | Change Directory - move to a new location |
ls | List - shows files and folders in current location |
ls -1 | List names only, one per line (screen reader friendly) |
ls -1 -F | List names with type indicators (/ for directories) |
ls *.extension | List 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
- Run
pwdand confirm your location - 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
- Run
pwdand confirm your location - Move to
Documents:cd Documents - Confirm you moved:
pwd - List files and folders:
ls -1 - List only files:
ls -1 -p | grep -v / - Go back up:
cd .. - 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
- What does
pwdshow? - How do you list directories only with
ls? - What wildcard matches any number of characters?
- How do you list files with the
.scadextension? - Give an example of an absolute path and a relative path.
- True or False: The
*wildcard matches exactly one character. - Explain the difference between
ls -1andls -1 -d */. - Write a command that would list all
.txtfiles in your Documents folder using a wildcard. - How would you search for files containing “part” in their name across multiple files?
- Describe a practical scenario where using wildcards saves time in a 3D printing workflow.
- What happens when you use
ls model?.scadversusls model*.scad? - How would you navigate to a folder whose name contains both spaces and special characters?
- If you’re in
~/Documents/Projects/3Dand you want to go to~/Documents/Resources, what command would you use? - Write a command sequence that navigates to the Downloads folder, lists only files, then returns to home.
- Explain the purpose of using
ls -1specifically in a screen reader context.
Extension Problems
- Write a one-line command that lists
.scadfiles and saves toscad_list.txt. - Use
ls -1 ~/Documents | lessto page through long listings. - Combine
lswithgrepto search for a filename pattern. - Create a shortcut alias in the session for a long path and test it.
- Practice tab-completion in a directory with many similarly named files.
- Build a bash script that recursively lists all
.scadand.stlfiles in a directory tree; save the results to a file. - Compare the output of
ls,ls -1,ls -la, andls -1 -d */to understand the flags; document what each command does. - Create a filtering command that displays only files modified in the last 7 days; test it on your documents folder.
- Write a non-visual guide to Git Bash navigation; include descriptions of common patterns and how to verify directory contents audibly.
- Develop a navigation workflow for a typical 3D printing project: move between CAD, slicing, and print-log folders efficiently; document the commands.
- Create a complex wildcard search: find all files in a folder and subfolders that match multiple patterns (e.g.,
*_v1.*or*_final.*). - Build a script that navigates through a folder tree, counts files at each level, and reports the structure.
- Document the output differences between
ls,ls -1,ls -la, andls -1 -d */; explain when to use each. - Create a navigation “cheat sheet” as a bash script that prints common paths and how to navigate to them.
- Design a project folder structure on your computer, document each path, then create a script that validates all folders exist.
References
- GNU. (2024). ls command reference. https://example.com
- GNU. (2024). Bash wildcards and globbing. https://example.com
- GNU. (2024). Navigation best practices in Bash. https://example.com
Helpful Resources
- ls Command Reference
- Bash Wildcards and Globbing
- Navigation Best Practices
- Relative and Absolute Paths in Bash
- Screen Reader Tips for Git Bash
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, andrmdirsafely - Understand when operations are permanent and how to confirm results
Materials
- Git Bash
- Small practice folder for exercises
Step-by-step Tasks
- Create a practice directory:
mkdir ~/Documents/GitBash_Practiceandcdinto it. - Create two files:
touch file1.txtandtouch file2.txt. - Copy
file1.txttofile1_backup.txtwithcpand confirm withls -1. - Rename
file2.txttonotes.txtusingmvand confirm. - Delete
file1.txtwithrmand 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
- How do you create an empty file from Git Bash?
- What command copies a file?
- How do you rename a file?
- What does
rm -rdo?
Warning
rmpermanently deletes files with no undo and no Recycle Bin. There is no recovery from Git Bash. Always runls -1first to confirm exactly what you’re targeting, especially when using wildcards.
- Why is
rmpotentially dangerous? - True or False:
cprequires the-rflag to copy both files and folders. - Explain the difference between
rmandrmdir. - If you delete a file with
rm, can you recover it from Git Bash? - Write a command that would copy an entire folder and all its contents to a new location.
- Describe a practical safety check you would perform before running
rm -ron a folder. - What happens if you
cpa file to a destination where a file with the same name already exists? How would you handle this safely? - Compare
mv old_name.txt new_name.txtvsmv old_name.txt ~/Documents/new_name.txt. What is the key difference? - Design a workflow to safely delete 50 files matching the pattern
*.bakfrom a folder containing 500 files. What commands and verifications would you use? - Explain how you could back up all
.scadfiles from a project folder into a timestamped backup folder in one command. - 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
- Create a folder tree and copy it to a new location with
cp -r. - Write a one-line command that creates three files named
a,b,cand lists them. - Move a file into a new folder and confirm the move.
- Use wildcards to delete files matching a pattern in a safe test folder.
- Export a listing of the practice folder to
practice_listing.txt. - Create a backup shell script that copies all
.scadfiles from your project folder to a backup folder with timestamp naming. - Build a safe deletion workflow: list files matching a pattern, verify count, then delete with confirmation; document the steps.
- Write a bash script that organizes files by extension into subfolders; test it on a sample folder tree.
- Create a file operation audit trail: log all copy, move, and delete operations to a text file for review.
- Develop a project template generator: a bash script that creates a standard folder structure for a new 3D printing project with essential subfolders.
- Implement a file conflict handler: write a bash script that handles cases where
cpwould overwrite an existing file by renaming the existing file with a timestamp before copying. - Create a batch rename operation: use a script to rename all files in a folder from
old_prefix_*tonew_prefix_*; test with actual files and verify the results. - 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.
- 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. - 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
- GNU. (2024). touch command reference. https://example.com
- GNU. (2024). cp and mv commands. https://example.com
- GNU. (2024). File system operations guide. https://example.com
Helpful Resources
- touch Command Reference
- cp Command Reference
- mv Command Reference
- rm Command Reference
- Safe Deletion Practices
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
echoto print text to the screen - Use
catto 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
| Command | What It Does |
|---|---|
echo "text" | Print text to the screen |
cat filename | Print the contents of a file |
> filename | Redirect output into a file (overwrites) |
>> filename | Append output to a file (adds to end) |
| | Pipe - send output from one command to the next |
clip | Copy piped input to the Windows clipboard (Git Bash) |
notepad.exe filename | Open 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
- Create
practice.txtwith three lines usingechoand>/>>. - Read the file with
cat practice.txt. - Pipe the file into
grepto search for a word. - Copy the file contents to clipboard with
cat practice.txt | clip. - Redirect
ls -1intolist.txtand open it in Notepad.
Checkpoints
- After step 3 you should be able to find a keyword using piping.
Quiz - Lesson GitBash.3
- What is the difference between
>and>>? - What does the pipe
|do? - How do you copy output to the clipboard?
- How would you page through long output?
- How do you suppress output (send it to
/dev/null)? - True or False: The pipe operator
|connects the output of one command to the input of another. - Explain why redirecting output to a file is useful for screen reader users.
- Write a command that would search for the word “sphere” in all
.scadfiles in a directory. - How would you count the number of lines in a file using bash piping?
- Describe a practical scenario in 3D printing where you would pipe or redirect command output.
- What would be the difference in output between
echo "test" > file.txt(run twice) vsecho "test" >> file.txt(run twice)? Show the expected file contents. - Design a three-step piping chain: read a file, filter for specific content, and save the results; explain what each pipe does.
- You have a 500-line
.scadfile and need to find all instances ofsphere()and count them. Write the command. - Explain how
clipis particularly valuable for screen reader users when working with file paths or long output strings. - Describe how you would use pipes and redirection to create a timestamped backup report of all
.stlfiles in a 3D printing project folder.
Extension Problems
- Use piping to count lines in a file (hint:
cat file.txt | wc -l). - Save a long
ls -1output and search it withgrep. - Chain multiple pipes to filter and then save results.
- Practice copying different command outputs to clipboard and pasting.
- Create a small bash script that generates a report (counts of files by extension).
- Build a data processing pipeline: read a text file, filter rows, and export results; document each step.
- Write a script that pipes directory listing to count occurrences of each file extension; create a summary report.
- Create a log analysis command: read a log file, filter for errors, and save matching lines to a separate error log.
- Design a piping workflow for 3D printing file management: find
.stlfiles, extract their names, and generate a report. - Develop a reusable piping function library: create bash functions for common filtering, sorting, and reporting patterns; test each with different inputs.
- Build a complex filter pipeline: read a
.scadfile, extract lines containing specific geometry commands, count each type, and output a summary to both screen and file. - Create an interactive filtering tool: build a bash script that accepts a search term, pipes through multiple filters, and displays paginated results.
- Develop a performance analysis tool: use piping to combine file listing, metadata extraction, and statistical reporting; export results to a dated report file.
- Implement a comprehensive error-handling pipeline: read output, catch errors, log them separately, and generate a summary of successes vs failures.
- 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
- GNU. (2024). Redirections in Bash. https://example.com
- GNU. (2024). grep command reference. https://example.com
- GNU. (2024). Bash pipeline concepts. https://example.com
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
- Show your username and home path with
echo $USERandecho $HOME. - Inspect
echo $PATHand identify whetheropenscadorcodewould be found. - Run
which openscadand note the result. - Create a temporary alias:
alias preview='openscad'and testpreview myfile.scad. - 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
- How do you print an environment variable?
- What is the purpose of
PATH? - How do you check whether
openscadis available? - How do you create a temporary alias?
- Where would you make an alias permanent?
- True or False: Environment variables in bash are case-sensitive.
- Explain why having a program in your PATH is useful compared to always using its full file path.
- Write a command that would create an alias called
slicerfor the OpenSCAD executable. - What file would you edit to make an alias persist across Git Bash sessions?
- Describe a practical benefit of using the
$TMPDIRor/tmpdirectory for temporary files in a 3D printing workflow. - You have a custom script at
~/scripts/backup_models.shthat you want to run from anywhere asbackup-now. What steps would you take to make this work? - Explain the difference between setting an environment variable in the current session with
exportvs. adding it to.bashrcfor permanence. - Design a
.bashrcstrategy for managing multiple 3D printing projects, each with different tool paths and directories; show how to structure environment variables for each. - If a program is not found by
which, what are the possible reasons, and how would you troubleshoot? - Describe how you would verify that your
.bashrcis loading correctly and how to debug issues if aliases or environment variables don’t appear after restarting Git Bash.
Extension Problems
- Add a folder to PATH for a test program (describe steps; do not change system PATH without admin).
- Create a short
.bashrcsnippet that sets two aliases and test re-opening Git Bash. - Use
whichto list the path for several common programs. - Explore
$TMPDIRor/tmpand create a file there. - Save a copy of your current PATH to a text file and examine it in your editor.
- Create a
.bashrcscript that loads custom aliases and environment variables for your 3D printing workflow; test it in a new session. - Build a “project profile” that sets environment variables for CAD, slicing, and print directories; switch between profiles for different projects.
- Write a script that audits your current environment variables and creates a summary report of what’s set and why.
- Design a custom alias system for common 3D printing commands; document the aliases and their purposes.
- Create a profile migration guide: document how to export and import your
.bashrcacross machines for consistent workflows. - 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. - Build a comprehensive
.bashrcframework with modular sourcing: create separate.shfiles for aliases, environment variables, and functions; have your main.bashrcsource all of them. - 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.
- 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.
- Build a
.bashrctroubleshooting 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
- GNU. (2024). Environment variables in Bash. https://example.com
- GNU. (2024). alias command reference. https://example.com
- GNU. (2024). Creating and using Bash profiles. https://example.com
Helpful Resources
- Environment Variables in Bash
- Understanding the PATH Variable
- Bash alias Reference
- Creating a Bash Profile (.bashrc)
- which Command for Locating Programs
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
.bashrcprofile 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
- Run several simple commands (e.g.,
pwd,ls -1,echo hi) then runhistoryto view them. - Use
!<n>to re-run a previous command by its history number (replace<n>with a history number). - Practice aborting a long-running command with
Ctrl + C(for example,ping google.com). - Open your profile:
notepad.exe ~/.bashrc; if it doesn’t exist, create it:touch ~/.bashrc. - Add a persistent alias line to your profile (example:
alias preview='openscad'), save, and runsource ~/.bashrcor 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
- How do you view the command history in Git Bash?
- Which key combination aborts a running command?
- What does
echo $BASH_VERSIONshow? - How does
./help run scripts and executables in the current directory? - What is one strategy if terminal output stops being announced by your screen reader?
- True or False: Using
Ctrl+Cpermanently deletes any files created by the command you abort. - Explain the difference between
historyandCtrl+R(reverse history search) in Git Bash. - If you add an alias to
.bashrcbut it doesn’t take effect after opening a new Git Bash window, what should you verify? - Write a command that would run a script at the path
~/scripts/openscad_runner.shdirectly. - Describe a practical workflow scenario where having keyboard shortcuts (aliases) in your
.bashrcwould save time. - 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). - Design a
.bashrcinitialization strategy that separates utilities for different projects; explain how you would switch between them. - 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?
- Create a safety checkpoint system: before any destructive operation (mass delete, overwrite), how would you use
.bashrcfunctions and history to verify the command is correct? - 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
- Add an alias and an environment variable change to your
.bashrcand document the behavior after reopening Git Bash. - Create a short bash script that automates creating a project folder and an initial
.scadfile. - Experiment with running OpenSCAD by full path using
./and by placing it in PATH; compare results. - Practice redirecting
man lsoutput to a file and reading it in Notepad for screen reader clarity. - Document three screen reader troubleshooting steps you used and when they helped.
- Build a comprehensive
.bashrcthat includes aliases, environment variables, and helper functions for your 3D printing workflow. - Create a bash script that troubleshoots common Git Bash issues (module loading, permission errors, command not found); test at least three scenarios.
- Write a bash function that coordinates multiple tasks: creates a project folder, starts OpenSCAD, and opens a notes file.
- Design a screen-reader accessibility guide for Git Bash: document commands, outputs, and accessible navigation patterns.
- Develop an advanced Git Bash workflow: implement error handling, logging, and confirmation prompts for risky operations.
- Implement an “undo” system using history: create a function that logs destructive commands (
rm,mv,cp) and allows you to review the last operation. - Build a
.bashrcdebugger: create a script that compares two Git Bash sessions’ environment states (variables, aliases, functions) to identify what loaded/failed to load. - 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.
- 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.
- 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
- GNU. (2024). Bash history and recall functionality. https://example.com
- GNU. (2024). Understanding and creating Bash profiles. https://example.com
- GNU. (2024). Running scripts and executables in Bash. https://example.com
Helpful Resources
- Bash History and Recall
- Understanding .bashrc
- history Command Reference
- Running Scripts with ./
- Screen Reader Tips and Tricks
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, runchmod +x batch_print.shonce to make it executable, then run with./batch_print.sh. If you forgetchmod +xyou’ll get “Permission denied” — just run thechmodcommand 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
.shscript, you must make it executable withchmod +x scriptname.sh. This is a one-time step per script. Without it, running./script.shwill 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/shis 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 functionlocal path="$1"assigns the first argument to a local variable$1is 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; doiterates over each.scadfile$fileholds the current filenamedoneends 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 withifrom 1 to 5$iis the counter variable
Real-World Example - Batch Processing SCAD Files
Scenario
You have 10 OpenSCAD (.scad) files in a folder. You want to:
- List them all
- Check how many there are
- 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 lookfor file in "$scad_folder"/*.scad= find all .scad filesif [ -f "$file" ]= check if file exists and is a regular filebasename "$file"= just the filename (not the full path)count=$((count + 1))= increment the counter
Running the Script
- Save as
batch-process.sh - Edit
scad_folderto match your real folder - 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/nullsuppresses error messages fromcatif cat ...; thenchecks whether the command succeededelsehandles 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 directoryreturn 1exits 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:
- Create file:
notepad.exe hello.sh - Type:
#!/bin/bash echo "Hello from my first Git Bash shell script!" pwd ls -1 - 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:
- Create file:
notepad.exe smart-listing.sh - Type:
#!/bin/bash target_folder="$HOME/Documents" echo "Listing contents of: $target_folder" ls -1 "$target_folder" - Edit
target_folderto a real folder on your computer - 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:
- Create file:
notepad.exe navigate.sh - 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" - 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:
- Create file:
notepad.exe repeat.sh - Type:
#!/bin/bash echo "Demonstrating a loop:" for i in $(seq 1 5); do echo "Iteration $i: Hello!" done echo "Loop complete!" - 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:
- Create a folder:
mkdir ~/Documents/TestFiles - Create some test files:
echo "test" > ~/Documents/TestFiles/file1.txt echo "test" > ~/Documents/TestFiles/file2.txt echo "test" > ~/Documents/TestFiles/file3.txt - Create script:
notepad.exe report.sh - 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 ===" - Run:
chmod +x report.sh ./report.sh
Checkpoint: Should show report of all files in the test folder.
Quiz - Lesson GitBash.6
- What is a shell script?
- What file extension do bash shell scripts use?
- What is a variable in bash and how do you create one?
- What is a function and why would you use one?
- How do you run a shell script?
- What is a
forloop and what doesfor file in *.scad; dodo? - What does
[ -f "$file" ]check? - How do you handle errors in a bash script?
- When would you use
if [ ! -d "$path" ]; then? - What technique makes shell script output readable for screen readers?
Extension Problems
- Auto-Backup Script: Create a bash script that copies all files from one folder to another, announcing progress
- File Counter: Write a function that counts files by extension (.txt, .scad, .stl, etc.)
- Folder Cleaner: Script that deletes files older than 30 days (with user confirmation)
- Project Template: Function that creates a complete project folder structure with all needed files
- Batch Rename: Script that renames all files in a folder according to a pattern
- Log Generator: Create a script that records what it does to a log file for later review
- Scheduled Task: Set up a script to run automatically using cron or Task Scheduler
- File Verifier: Check that all SCAD files in a folder have corresponding STL exports
- Report Generator: Create a summary report of all projects in a folder
- 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
- GNU Bash Scripting Guide: https://example.com
- Function Documentation: https://example.com
- Error Handling: https://example.com
- Loops: https://example.com
Unit Exam — Comprehensive Assessment
Estimated time: 60-90 minutes
Key Learning Outcomes Assessed
By completing this unit test, you will demonstrate:
- Understanding of file system navigation and path concepts
- Proficiency with file and folder manipulation commands
- Ability to redirect and pipe command output
- Knowledge of environment variables and aliases
- Screen-reader accessibility best practices in terminal environments
- 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.
-
What is the primary purpose of the
PATHenvironment 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
-
Which command prints your current working directory in Git Bash?
- A)
ls -1 - B)
cd - C)
pwd - D)
whoami
- A)
-
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
-
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
- A)
-
Which command creates a new empty file in Git Bash?
- A)
mkdir filename - B)
touch filename - C)
new filename - D)
echo filename
- A)
-
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
- A)
-
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
-
Which command copies a file in Git Bash?
- A)
mv - B)
rm - C)
cp - D)
cd
- A)
-
How do you rename a file from
oldname.txttonewname.txtin 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
- A)
-
What is the purpose of
grepin 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
-
Which key allows you to autocomplete a path in Git Bash?
- A)
Ctrl + A - B)
Ctrl + E - C)
Tab - D)
Space
- A)
-
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
- A)
Tip
Use
which programnameto check whether a program is in your PATH and find its full path. Ifwhich openscadreturns nothing, OpenSCAD is not in your PATH and you’ll need to add it or call it by its full path.
-
What does
which openscaddo?- 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
-
Which wildcard matches any single character in Git Bash?
- A)
* - B)
? - C)
% - D)
#
- A)
-
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
-
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
- A)
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, runsource ~/.bashrcto apply changes without restarting.
- Where is a Git Bash alias typically stored to persist across sessions?
- A)
C:\Program Files\Git\profile.sh - B) In the
~/.bashrcfile - C)
~/bash_profile - D) Aliases cannot be made permanent
- A)
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.
-
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
- A) Press
-
What command shows the history of previously run commands in Git Bash?
- A)
history - B)
get-history - C)
show-history - D)
bash-history
- A)
Tip
After editing
~/.bashrc, runsource ~/.bashrcto 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.
- How do you reload your
.bashrcwithout restarting Git Bash?- A) Use
reload ~/.bashrcin the terminal - B) Use
source ~/.bashrc - C) Use the Windows Control Panel
- D)
.bashrcreloads automatically
- A) Use
Part B: Short Answer Questions (10 questions)
Answer each question in one to two sentences. Each question is worth 2 points.
-
Explain the difference between absolute and relative paths. Give one example of each.
-
Why is
ls -1preferred overlsfor screen reader users? Describe what flag combination you would use to list only directories. -
What is the purpose of redirecting output to a file, and give an example of when you would use
>instead of>>? -
Describe what would happen if you ran
rm -r ~/Documents/my_folderand why this command should be used carefully. -
How would you search for all files with a
.scadextension in your current directory? Write the command. -
Explain what happens when you pipe the output of
ls -1intoclip. What would you do next? -
What is an environment variable, and give one example of how you might use it in Git Bash.
-
If a program is not in your
PATH, what two methods could you use to run it from Git Bash? -
Describe how you would open a file in Notepad and also add a line to it from Git Bash.
-
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
-
Create a folder structure
~/Documents/GitBash_Assessment/Projectsusing a single command. Capture thels -1output showing the creation. -
Create five files named
project_1.scad,project_2.scad,project_3.txt,notes_1.txt, andnotes_2.txtinside theProjectsfolder. Use wildcards to list only.scadfiles, then capture the output. -
Copy the entire
Projectsfolder toProjects_Backupusingcp -r. Capture thels -1output showing both folders exist. -
Move (rename)
project_1.scadtoproject_1_final.scad. Capture thels -1output showing the renamed file. -
Delete
notes_1.txtandnotes_2.txtusing a singlermcommand with wildcards. Capture the finalls -1output.
Tasks 6-10: Advanced Operations and Scripting
-
Create a file called
my_data.txtwith at least four lines usingechoand>>. Then read it withcat my_data.txtand capture the output. -
Use
grepto search for a keyword (e.g., “project”) inmy_data.txtand pipe the results toclip. Paste the results into Notepad and capture a screenshot. -
List all files in the
Projectsfolder and redirect the output toprojects_list.txt. Open it in Notepad and capture a screenshot of the file. -
Create a temporary alias called
mylsthat runsls -1, test it, and capture the output. Then explain what would be required to make it persistent. -
Run
man ls(orls --help) and redirect the output tohelp_output.txt. Open the file in Notepad and capture a screenshot showing at least the first page of help content.
Grading Rubric
| Section | Questions | Points Each | Total |
|---|---|---|---|
| Multiple Choice | 20 | 1 | 20 |
| Short Answer | 10 | 2 | 20 |
| Hands-On Tasks | 10 | 3 | 30 |
| Total | 40 | - | 70 |
Passing Score: 49 points (70%)
Helpful Resources for Review
- Git Bash Command Reference
- Navigation and File System
- Using Pipes and Filtering
- Bash Profile and Aliases
- Screen Reader Accessibility Tips
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 Component | Primary Source Filaments | Mitigation 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
$fnvalues. Keep$fnlow 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
| Limitation | Technical Root Cause | Educational Impact |
|---|---|---|
| CLI Barrier | No graphical interface for configuration | Steep learning curve for students with zero terminal experience.3 |
Caution
AI features (
3dm infodescriptions,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 theslicecommand 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
- Nation of Makers — U.S. crowdsourced map of makerspaces and hackerspaces
- Makerspace.com Global Directory — Worldwide listing with search and filters
- Makerspace Directory (makerspacedir.com) — U.S.-focused, covers Fab Labs, youth programs, and coworking hybrids
- WorkMakeCreate — Find free and public makerspaces by ZIP code
Supplemental Learning Resources
- Programming with OpenSCAD: A Beginner’s Guide to Coding 3D-Printable Objects — Complete reference covering syntax, geometry concepts, design patterns, and best practices
- Simplifying 3D Printing with OpenSCAD — Focused guide to practical workflows, optimization, and real-world printing
- CodeSolutions Repository — Working OpenSCAD examples organized by topic and difficulty
- Practice Worksheets and Guides — Printable materials for visualization practice and assessment
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
| # | Title | Duration | Level | Key Project |
|---|---|---|---|---|
| 1 | Environmental Configuration | 2.5–3.5 hrs | Beginner | Project scaffold |
| 2 | Geometric Primitives & CSG | 60 min | Beginner | 3 CSG examples |
| 3 | Parametric Architecture | 2.5 hrs | Beginner+ | Parametric bracket |
| 4 | AI Verification | 2–2.5 hrs | Intermediate | AI-notes.md |
| 5 | Safety & Physical Interface | 2.5–3.5 hrs | Intermediate | Pre-print checklist |
| 6 | 3dm Commands & Text Embossing | 2.5–3.5 hrs | Intermediate | Keycap variants |
| 7 | Parametric Transforms | 3–3.5 hrs | Intermediate+ | Phone Stand |
| 8 | Advanced Parametric Design | 90–120 min | Advanced | Stackable Bins |
| 9 | Automation & Workflows | 2.5–3.5 hrs | Advanced | Batch build script |
| 10 | Troubleshooting & Mastery | 5–6 hrs | Advanced | 3 complete projects |
| 11 | Stakeholder-Centric Design | 3.5–4.5 hrs | Advanced+ | 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
| Project | Lessons | Output Files | Est. Print Time |
|---|---|---|---|
| Keycap Set | 1–6 | 5+ SCAD files, 3+ STL files | 15–30 min total |
| Phone Stand | 1–7 | 1 SCAD with 3+ variants | 30–60 min total |
| Storage Bins | 1–8 | 1 parametric SCAD, 3 sizes | 60–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
| Appendix | Focus | Size | Use When |
|---|---|---|---|
| A: Comprehensive Slicing Guide | PrusaSlicer, Bambu Studio, Cura, OrcaSlicer, and more | 1,500+ lines | Slicing questions, slicer reference |
| B: Material Properties & Selection | PLA, PETG, ABS, TPU, Polycarbonate, Nylon — properties, settings, decision tree | 1,200+ lines | Choosing material, troubleshooting prints |
| C: Tolerance Testing & QA Matrix | Measurement procedures, functional testing, stack-up calculations | 1,200+ lines | Quality verification, measurement techniques |
| D: PowerShell Integration | Batch processing, automation scripts, workflow integration | 1,100+ lines | Building automation, batch processing |
| E: Advanced OpenSCAD Concepts | Gears, batch/statistical analysis, performance optimization, recursion | Optional | Specialized/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
| Version | Date | Changes |
|---|---|---|
| 2.1 | Feb 2026 | Added Appendix E (Advanced OpenSCAD); Enhanced Lessons 3, 6, 7, 8, 9 with advanced topics |
| 2.0 | Feb 2026 | Added Lesson 11 (Stakeholder Design) + 4 Appendices; Consolidated Units 0–3 content |
| 1.0 | Feb 2026 | Initial 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
.scadfile - Read and interpret
3dm infooutput 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 Linux —
3DMand3dmare 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 usetranslate()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 run3dm build. All your actual work goes insrc/.
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
| Concept | Key Point |
|---|---|
| Parametric design | Change one number, model updates everywhere it’s used |
| OpenSCAD | Code-based 3D geometry engine; you describe shapes with text |
| 3dMake | Project manager layer; 3dm build and 3dm info are your main commands |
| Units | Always millimeters — no exceptions |
| Origin (0,0,0) | Front-left corner of build space, at bed level |
| X axis | Points right |
| Y axis | Points away from you (back) |
| Z axis | Points straight up |
center=false | Default — one corner of the object sits at the specified position |
center=true | Object straddles the specified position (center is at that point) |
3dm build | Compiles src/main.scad → build/main.stl |
3dm info | Reports bounding box, volume, triangle count, AI description |
3dm watch | Auto-rebuilds whenever you save a .scad file |
| Bounding box | Smallest rectangle containing the whole model — your #1 verification metric |
| STL file | Triangle-mesh representation of surface geometry |
| FDM pipeline | STL → Slicer → G-code → Print → Cool |
| Layer height | Thickness of each printed layer; 0.20 mm is a good default |
| Infill | Internal density; 15–20% for typical parts, 40–50% for structural |
| Supports | Temporary 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 basics02_parametric_phone_stand(Intermediate) — Transforms and Minkowski fillets03_stackable_bins(Advanced) — Tolerance and assemblies
Reference Materials (Reference_Materials/)
3dmake-setup-guide.md— Complete setup walkthroughopenscad-cheat-sheet.md— Keyboard shortcuts and common functionsfilament-comparison-table.md— Material properties referencemaster-rubric.md— Assessment criteria
Quiz — Lesson 1 (15 questions)
- What command initializes a 3dMake project?
- What folder holds generated STL files?
- How do you run 3dMake’s automatic rebuild mode?
- Why is it useful to run
3dm buildfrequently during development rather than only at the end? - Give one reason to prefer an external text editor over the built-in OpenSCAD editor for this workflow.
- True or False: 3dMake requires a graphical user interface to use effectively.
- Explain what the
3dmake.tomlfile does in your project. - Describe what the
src/andbuild/project folders are used for and which one you edit directly. - 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?
- What validation step should you always perform after running
3dm buildbefore sending a file to print? - If the bounding box reported by
3dm infoshows0 × 0 × 0 mm, what does that tell you, and what should you do next? - Explain what
center=falseandcenter=truemean for acube(). For each, where does the object appear relative to the position you specify? - What does FDM stand for, and what are the five stages of the FDM pipeline from STL file to cooled physical part?
- 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.
- You run
3dm buildand receive the error “No such file or directory: src/main.scad”. List two likely causes and the fix for each.
Extension Problems (15)
- Add a README entry explaining your top-level parameters and expected units.
- Create a parameter variant by changing
widthby 20% and build both variants; compare dimensions using3dm infoto confirm the change. - Script a command sequence that automates the entire new-project setup: create folder, create
src/main.scad, and run3dm build— in a single script file. - Intentionally introduce a syntax error in your
.scadfile (remove a semicolon), run3dm build, and document what the error message says and which line it points to. Then fix it. - Prepare a short instructor sign-off checklist describing the safety checks you should complete before sending a file to print.
- Build a variant testing suite: create 5 different combinations of
width,depth, andheight, build all five, and record the bounding box and volume for each. - Create a 3dMake project template with best-practice structure, documentation header, and parameter comments. Write a README explaining how to use it.
- Write a short accessibility guide explaining how a student using a screen reader could use
3dm infooutput to understand a model’s geometry without a visual preview. - Design a simple parametric part library (three or more related parts) in a single project. Document all parameters with units and example values.
- Write a comprehensive troubleshooting guide for common
3dm builderrors, with the cause and fix for each. - Add a
.gitignorefile 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. - Edit the global configuration file using
3dm edit-global-configto change the default editor. Document the setting name and how you verified the change took effect. - Create a project with three
.scadsource files and build each using3dm build -m <n>. Record the output STL filenames. - 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?
- 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
-
Choose a simple model (under 2 hours estimated print time) from Thingiverse or Printables. Download the STL.
-
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.
-
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.
-
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.
-
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
- Why did you select this model? What specific risks did you anticipate, and how does this model avoid or minimize them?
- Which slicer setting most affects print time for this model, and why?
- 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
| Parameter | Value |
|---|---|
| Printer model | |
| Nozzle diameter | mm |
| Nozzle temperature | °C |
| Bed temperature | °C |
| Layer height | mm |
| Infill % | |
| Support settings | |
| Print speed | mm/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
Print Monitoring Notes
- 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:
| Feature | Model 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
| Category | Score (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
| Command | Purpose | Notes |
|---|---|---|
3dm init | Initialize a new project | Run once per project |
3dm build | Compile source → STL | Run after every code change |
3dm info | Report dimensions and AI description | Always run before sending to print |
3dm preview | Render model image | Use for quick visual check |
3dm orient | AI print orientation suggestion | Use as a starting point, verify yourself |
3dm slice | Run slicer on current build | Requires slicer path in 3dmake.toml |
3dm edit-global-config | Edit the global settings file | For 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 chapterRight 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.
| Key | Action |
|---|---|
S | Focus the search box |
Escape | Close search results |
Left Arrow | Previous chapter |
Right Arrow | Next chapter |
T | Toggle the table of contents sidebar |
Screen Reader Navigation
With NVDA (Chrome, Firefox, or Edge recommended)
H— jump between headings; the fastest way to skim a long lessonD— 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 + Pto cycle Ctrl + F— browser Find, works alongside mdBook search
With JAWS (Chrome or Edge recommended)
H— jump between headingsR— move between landmark regions to reach the sidebarJAWS Key + F6— list all headings on the current page- Set punctuation to All before reading code:
JAWS Key + Shift + 2 JAWS Key + F5— links listCtrl + F— browser find
With VoiceOver (Mac / iOS)
VO + U— open the rotor; select Headings to navigate by headingH(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.
| Action | Keys |
|---|---|
| Read current line | NVDA + Up Arrow |
| Spell current line | NVDA + Up Arrow (twice quickly) |
| Read from cursor | NVDA + Down Arrow |
| Read current word | NVDA + Numpad 5 |
| Spell current word | NVDA + Numpad 5 (twice quickly) |
| Stop reading | Ctrl |
Navigation in VSCode with NVDA:
| Action | Keys |
|---|---|
| Move by character | Left / Right Arrow |
| Move by word | Ctrl + Left / Right Arrow |
| Move by line | Up / Down Arrow |
| Start / end of line | Home / End |
| Go to line number | Ctrl + G, type number, Enter |
| Find text | Ctrl + F |
| Toggle line comment | Ctrl + / |
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.
| Action | Keys |
|---|---|
| Read current line | JAWS Key + Up Arrow |
| Spell current line | JAWS Key + Up Arrow (twice quickly) |
| Read from cursor | JAWS Key + A |
| Read current word | JAWS Key + Numpad 5 |
| Stop reading | Ctrl |
| Increase speech rate | Alt + Ctrl + Page Up |
| Decrease speech rate | Alt + Ctrl + Page Down |
Navigation in VSCode with JAWS:
| Action | Keys |
|---|---|
| Move by character | Left / Right Arrow |
| Move by word | Ctrl + Left / Right Arrow |
| Move by line | Up / Down Arrow |
| Go to line number | Ctrl + G |
| Find text | Ctrl + F |
| Toggle comment | Ctrl + / |
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 message | What it usually means |
|---|---|
Expected ';' ... | Missing semicolon at end of a statement |
Expected ',' or ')' ... | Missing comma between parameters, or unclosed parenthesis |
Identifier ... is undefined | Variable name typed wrong, or used before declaration |
WARNING: Normalized tree is empty | Shape 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.
- Measure → say “seventy point three millimeters”
- Type
70.3in OpenSCAD - 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:
- Press
Ctrl + Shift + Pto open the Command Palette - Type
Tasks: Configure Taskand press Enter - 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 + Pto 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
| Problem | Solution |
|---|---|
| OpenSCAD doesn’t open | Confirm openscad --version works in PowerShell |
| VSCode not read by screen reader | JAWS: press JAWS Key + Z to exit Virtual mode; NVDA: click inside the editor once to confirm focus |
| Can’t find error in code | Error includes a line number — use Ctrl + G to jump to it |
.scad has an error | Alt + 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(), andintersection() - 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()andlinear_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=5creates a cone that’s wider at the bottom and narrower at the topr1=8, r2=0creates a spike — the top radius is zero, so the top comes to a pointr1=0, r2=8creates 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:
- Create a box
- Create a cylinder the size of the hole
- 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:
- Create the main body as a box
- Create a sphere slightly larger than the corner radius
- 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 yourdifference()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. Atwist=90on a square profile creates a twisted square column.scale=factor— changes the size of the profile from bottom to top.scale=0.5means 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)
- What are the four main 3D primitives in OpenSCAD?
- What does
difference()do? Which child is the base, and which children are the cutting tools? - Why do you add 0.001 mm to the cutting geometry in a
difference()operation? What problem does it prevent? - What does the
#modifier character do, and when would you use it during debugging? - What is the difference between F5 and F6 in the OpenSCAD GUI? Which should you use before printing?
- What does
hull()produce? How is it different fromunion()? - What does the
%modifier do to a shape in OpenSCAD? - Describe what
rotate_extrude()does and give one example of a shape it could produce. - What does
intersection()return when applied to a cube and a sphere that partially overlap? - True or False: the
*modifier renders a shape as a transparent ghost for debugging purposes. - Describe what
linear_extrude()does and explain what thetwistparameter changes. - What is a co-planar face, and what problem does it cause in a
difference()operation? - 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?
- When using
polygon(), what order should points be listed in, and why? - What is the difference between combining two overlapping shapes with
union()versus rendering two separate overlapping objects without any CSG operation?
Extension Problems (15)
- 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 using3dm info. - 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. - Design a bracket or clip using nested
difference()andunion(). Add a comment to every CSG step explaining what it does. - Use
hull()to create a smooth, rounded box with 3 mm radius corners. Document the sphere placement strategy you used. - 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. - Create a parametric name badge: a flat rectangular base with your name text embossed (raised) on the top face, using
linear_extrude()combined withtext(). Make the text height a parameter. - 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. - Design a 10-sided (decagonal) prism using
cylinder()with$fn=10and adifference()to cut a hexagonal through-hole aligned with the prism’s center. - 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. - Using only
cube(),sphere(),difference(), andhull(), build a simple chess pawn. It should be recognizable as a pawn when printed. - 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.
- Build a parametric ring using
rotate_extrude()where the cross-section shape (round, square, or custom polygon) is easily changeable by modifying a variable. - Research and document the
surface()primitive: what input does it accept, what shape does it produce, and when would you use it instead ofpolyhedron()? Include a working example. - 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.
- 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)
| Modifier | Effect | When to use |
|---|---|---|
# | Highlight shape in red/orange | Finding where a hole or subtractive shape is |
% | Render shape as transparent ghost | Checking alignment of mating parts |
! | Render ONLY this shape | Isolating one component for inspection |
* | Disable (ignore) this shape | Temporarily 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
| Key | Action |
|---|---|
F5 | Preview — fast, approximate (use for checking while designing) |
F6 | Full render — exact, required before export |
Ctrl + S | Save |
Ctrl + Z | Undo |
F3 | Reset camera view |
Export Workflow
- Press
F6(full render — wait for it to complete) - File → Export → Export as STL
- Save with a descriptive filename:
projectname_v2.stl - Run
3dm infoon 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
-
Choose a model from Thingiverse or Printables. Note its original stated dimensions.
-
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?
-
Apply the change in OpenSCAD (preferred) or by scaling in the slicer. Record the new dimensions and what changed relative to the original.
-
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.
-
Create a short construction note: describe how the modified print is used or assembled. Photograph the result.
Probing Questions
- What motivated the modification, and who benefits from it?
- 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
| Variant | Scale or Change | Est. print time | Est. filament (g) | Key dimensions |
|---|---|---|---|---|
| Original (reference) | — | |||
| V1 (your modification) | ||||
| V2 (optional) |
Print Results
| Variant | Actual print time | Actual filament (g) | Quality | Notes |
|---|---|---|---|---|
| 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
-
.scadfile 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
| Category | Score (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
-
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.
-
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.
-
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.
-
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.
-
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
- What assumptions did you make about the user’s context? How could you validate those assumptions with someone other than yourself?
- 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 source | Why it could work | Why it might not work |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 |
Selected model: _____ Reason for selection:
Modification Changelog
| # | Change made | Why | Result |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 |
Original vs. Adapted Specifications
| Parameter | Original | Adapted | Reason |
|---|---|---|---|
Design Iteration Cycle
Print 1
- Date:
- Settings (layer height, infill, supports):
- Result:
- Issues observed:
- Next action:
Print 2 (if made)
- 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
-
.scador.stlfiles for each iteration - Photos of each printed iteration
- Test results documentation
- Final report (performance summary and next steps)
Teacher Feedback
| Category | Score (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
useandinclude - 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
forloops, conditionals, and list comprehensions to generate repetitive geometry - Write type-safe modules using
is_number(),is_list(), andis_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. Preferusefor 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)→ isn <= 1? No. → return5 * factorial(4)factorial(4)→ isn <= 1? No. → return4 * factorial(3)- …and so on until…
factorial(1)→ isn <= 1? Yes. → return1
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)
- What is the DRY principle and why is it important in parametric OpenSCAD design?
- What is the difference between a module and a function in OpenSCAD?
- What does
include <library.scad>do differently fromuse <library.scad>? When would you use each? - If you write
x = 5;on line 3 andx = 10;on line 20 in the same file, what is the value ofxeverywhere in that file? Why? - What does
is_number()return, and give one example of when to use it in a module. - What does the list comprehension
[for (i=[0:5:20]) i*2]evaluate to? - What does the
echo()function do in OpenSCAD, and where does its output appear? - True or False: a function in OpenSCAD can contain a
cylinder()call and create geometry. - How do you specify a default parameter value in an OpenSCAD module? Write an example.
- What is the ternary operator in OpenSCAD? Write an example that picks a box size based on a
"small"or"large"variable. - Write an OpenSCAD
forloop that places 8 cylinders evenly spaced around a circle of radius 25. - What is the difference between
[0:10]and[0:2:10]as OpenSCAD range expressions? - Explain why you might use
assert()in a module rather than relying on the caller to pass correct values. - Describe how a recursive function works. What are the two required parts of any recursive function?
- A library file called
shapes.scadcontains amodule rounded_box(...)and also a top-levelcube([5,5,5]);. What happens when you load it withuse? What happens when you load it withinclude?
Extension Problems (15)
- Create a
bolts.scadlibrary with M3, M4, and M5 clearance holes and nut traps. Use it in a test plate with one of each type. - Build a parametric pegboard using a
forloop. Parameters:cols,rows,spacing,peg_r,peg_h. Every parameter should have anassert()validation. - Implement a recursive function that generates a Fibonacci sequence up to
nterms and use it to space objects with Fibonacci distances. - Build a module that validates all its inputs using
assert()and logs informational output withecho(). Document whenassert()halts rendering vs. whatecho()does. - Create two library files — one for mechanical fasteners and one for decorative shapes — and use both in one combined project.
- Design a parametric gear profile module with
teeth,module_size, andthicknessparameters. Useassert()to validate that the number of teeth is at least 8. - Build a “shelf peg” system: a board with N parametrically positioned holes and matching pegs sized to press-fit into them.
- Use a list comprehension to generate a spiral path of evenly-spaced points and place a small sphere at each point on the spiral.
- Extend a fastener library with threaded insert pockets for M3, M4, and M5 heat-set inserts, with the insert dimensions as parameters.
- Write a module that draws a text label with a surrounding rectangular border frame. Parameters:
text_str,font_size,padding,border_thickness. - Build a parametric snap-fit lid for a rectangular box using
forloops to generate evenly-spaced snap clips around the perimeter. - Write a module that takes a list of 3D coordinate vectors as input and draws a connecting chain of cylinders between consecutive points.
- Create a parametric honeycomb panel module. Parameters:
rows,cols,cell_r,wall_t,depth. Each cell should be a hexagonal through-hole. - 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.
- 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
forloop.
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
- Programming with OpenSCAD EPUB Textbook — Chapters on modules, functions, and libraries
- CodeSolutions Repository — Worked examples for parametric architecture
- BOSL2 GitHub Repository — Comprehensive parametric library
- 3DMake GitHub Repository — Build workflow reference -e
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 infoeffectively 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 previewand 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 Type | What It Checks | Reliability |
|---|---|---|
3dm info bounding box & volume | Exact model dimensions | Deterministic — identical every run |
3dm info AI description | Overall shape, component layout | Non-deterministic — may vary |
| Slicer layer view | Wall thickness, internal features, overhangs | Deterministic — reliable for geometry |
| Physical calipers | Printed part dimensions | Ground truth — most authoritative |
assert() guards | Parameter validity before render | Deterministic — runs at build time |
Quiz — Lesson 4 (15 questions)
- What does
3dm infodo? What two fundamentally different types of information does it provide? - What is the key difference between deterministic validation and AI-based validation?
- Give two specific examples of information that
3dm info’s AI description cannot reliably provide. - In the verification escalation chain, which level provides “ground truth” for dimensional accuracy, and why?
- List three common errors that AI tools make when generating OpenSCAD code.
- True or False: the bounding box reported by
3dm infomight be slightly different each time you run it on the same file. - What data privacy concern should you consider before uploading a proprietary design to a cloud AI service?
- What does the slicer layer view let you verify that the bounding box cannot show?
- What two characteristics distinguish a strong AI code review prompt from a weak one?
- 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?
- What is “prompt engineering” and why does it matter when asking an AI to review OpenSCAD code?
- Write an
assert()statement that ensures a variable calledlayer_heightis between 0.05 mm and 0.4 mm. - What is the advantage of using
assert()at the top of a file compared to manually checking parameter values before every build? - Describe one scenario where AI validation would be genuinely useful and one where you must rely on deterministic tools instead.
- 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)
- 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.
- 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.
- Run
3dm infoon 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? - Create a structured accept/reject log for one full design cycle: design → verification checklist → AI review → physical test → decision to print or revise.
- 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.
- 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.
- 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?
- Build a “verification script” that automatically runs
3dm build, checks the exit code, runs3dm info, and extracts the bounding box for comparison against expected values. - 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?
- 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?
- 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.
- Research and document what “manifold” means in geometry. What makes a mesh non-manifold? What are the three most common causes in OpenSCAD?
- 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.
- 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. - 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
-
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. -
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.
-
Print one sample of each variant. Use the same material and layer height for all three to isolate the design variable.
-
Durability test: five throws onto a soft surface for each die. Record whether any delamination, corner chipping, or pip damage is visible after testing.
-
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%.
-
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
wallandpip_depth. To create Variant 3, changedie_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 aminkowski()of a smaller cube and asphere(r=corner_r)— see the AI code gallery in Appendix D for a worked example of this technique.
Quiz Questions (from workshop)
- What parameter controls wall thickness in your
.scadfile? - Name one method to increase a die’s impact resistance without changing its overall size.
- How would you test a die for randomness? What is the minimum number of rolls for a meaningful result?
- Why might a hollow die behave differently from a solid one of the same external dimensions?
- What is a simple visual sign of print-layer delamination on a die?
- True or False: A perfectly fair die must have uniform weight distribution throughout, including the internal structure.
- Describe two design approaches for rendering the face numbers: one using
difference()to create sunken pips, one usinglinear_extrude()for raised numbers. - 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.
- 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
- 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
| Parameter | Variant 1 | Variant 2 | Variant 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:
| Measurement | Variant 1 | Variant 2 | Variant 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).
| Throw | Variant 1 — Observations | Variant 2 — Observations | Variant 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: ____
| Face | Tally (mark each roll) | Frequency | Percentage | Expected (16.67%) | Deviation |
|---|---|---|---|---|---|
| 1 | % | 16.67% | |||
| 2 | % | 16.67% | |||
| 3 | % | 16.67% | |||
| 4 | % | 16.67% | |||
| 5 | % | 16.67% | |||
| 6 | % | 16.67% | |||
| Total | 100 | 100% | 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
-
Were you surprised by the fairness test results? Did the die perform better or worse than you expected?
-
Which design parameter had the largest effect on the test outcome, and what does that tell you about the physics of the die?
-
What would you change in a fourth iteration to improve fairness?
-
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
-
.scadfile 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 infofor each variant
Teacher Feedback
| Category | Score (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
.scadfile 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.
Appendix D: AI Guidance — Advantages, Disadvantages, and Flawed Code Gallery
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 build → 3dm 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.
D3 — Flawed AI-Generated OpenSCAD — Debugging Gallery
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.
| Material | Fume Risk | Required Mitigation |
|---|---|---|
| PLA | Low | Good room ventilation (open window or HVAC on) |
| PETG | Low–Medium | Active 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:
| Filament | Strength | Flexibility | Heat Resistance | Print Difficulty | Best Uses |
|---|---|---|---|---|---|
| PLA | Medium | Rigid | Low (softens at 50–60°C) | Easy | Prototypes, display models, artwork, educational parts |
| PETG | Medium-High | Slightly flexible | Medium (75–80°C) | Easy–Medium | Functional parts, food-adjacent applications, water contact |
| ABS | High | Semi-rigid | High (85–100°C) | Hard | Hot environments, automotive interiors, post-processing (acetone smoothing) |
| TPU | Medium | Very flexible | Medium | Medium | Gaskets, grips, phone cases, flexible joints |
| Nylon | Very High | Flexible | High | Hard | Mechanical parts, gears, load-bearing functional parts |
| ASA | High | Semi-rigid | Very High (90°C+) | Hard | Outdoor 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.
-
Wait for the nozzle to cool below 50°C before reaching anywhere near the hot end.
-
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.
-
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)
- What are the five levels of the Hierarchy of Controls, from most to least effective?
- Why is Elimination considered the most effective safety control?
- Which filament requires a dedicated fume enclosure with HEPA + activated carbon filtration and is NOT recommended for open classrooms?
- At what temperature should you wait before removing a print from the bed?
- What should you do immediately if you see smoke coming from your 3D printer?
- Give three reasons why PLA is considered the safest classroom filament.
- What is the minimum reliable wall thickness for a 0.4 mm nozzle, and why does this minimum exist?
- What is the purpose of storing filament with desiccant?
- True or False: It is safe to leave a 3D printer completely unattended for hours once the first layer has printed successfully.
- What is “spaghetti” in the context of a 3D printing failure, and what causes it?
- What is thermal runaway protection, and why is it critical that it remain enabled?
- What are the two types of airborne emissions from FDM printing, and which filaments produce the most hazardous levels of each?
- Describe one engineering control and one administrative control you could implement in a classroom 3D printing lab.
- Explain why minimizing overhangs in your design is both a safety consideration and a quality consideration.
- 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)
- Create a material selection flowchart that guides a user from mechanical requirements to the safest filament that meets them.
- Conduct a ventilation assessment of your classroom or makerspace. Document air exchange methods, window locations, and any existing filtration.
- Write a Standard Operating Procedure (SOP) for ABS printing that includes all required safety equipment and ventilation infrastructure.
- 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.
- Build a parametric filament storage clip in OpenSCAD: a clip that holds the free end of a filament spool. Parameters: filament diameter, clip width.
- Research OSHA’s published guidance on VOC exposure in 3D printing environments. Summarize the key recommendations.
- Compare the Safety Data Sheets (SDS) for PLA and ABS filament from two manufacturers. Document differences in recommended exposure limits and PPE.
- 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.
- Create a safety poster covering the five most important 3D printing safety rules, organized using the Hierarchy of Controls framework.
- Write a one-page risk assessment for a new FDM printer being added to a classroom.
- Design and describe a parametric filament moisture indicator holder: a small box that holds a humidity indicator card inside a resealable filament storage bag.
- Build a “print monitoring log” template: a paper form with columns for time, nozzle temperature, bed temperature, layer number, visual observations, and action taken.
- Research the difference between particle emissions and VOC emissions from FDM printing. Which is considered more hazardous at typical classroom distances from the printer?
- 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.
- 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
| Hazard | Temperature / Condition | Response |
|---|---|---|
| Hot nozzle | 190–260°C | Do not touch; wait for < 50°C |
| Hot bed | 50–110°C | Do not touch; allow full cool-down |
| Fumes (ABS/PETG) | At operating temp | Ventilate; use enclosure with filtration |
| Electrical (power supply) | 120V / 240V mains | Never open while plugged in |
| Tangled filament | Any | Clear 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
| Property | PLA | PETG | TPU (Flex) | ABS |
|---|---|---|---|---|
| Difficulty | Easiest | Moderate | Hard | Very Hard |
| Nozzle temp | 190–220°C | 230–250°C | 220–240°C | 230–250°C |
| Bed temp | 50–60°C | 70–85°C | 30–60°C | 90–110°C |
| Enclosure needed? | No | No | No | Yes |
| Rigidity | High | Medium | None — flexible | High |
| Impact resistance | Low (brittle) | Medium | Very high | Medium |
| Heat resistance | Low (~60°C) | Medium (~80°C) | Medium | High (~100°C) |
| Flexibility | None | Slight | Rubber-like | None |
| Moisture sensitivity | Low | Medium | High | Medium |
| Fume concern | Lowest | Low | Moderate | High |
| Bed adhesion | Easy | Use glue stick on PEI | Easy | Requires enclosure + glue |
| Print speed | Normal | Normal | Slow (20–30 mm/s) | Normal |
| Stringing tendency | Low | Medium–High | High | Low |
| Approximate cost | $15–25/kg | $15–30/kg | $20–40/kg | $15–25/kg |
| Recommended for beginners? | ✅ Yes | After PLA | After 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
| Filament | PrusaSlicer Profile | Key Changes from PLA Default |
|---|---|---|
| PLA | Generic PLA | Baseline — no changes needed |
| PETG | Generic PETG | Higher temps; slower cooling; glue stick on PEI bed |
| TPU | Generic Flex | Reduce speed to 20–30 mm/s; reduce retraction |
| ABS | Generic ABS | Higher 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.
| Filament | Moisture Sensitivity | Storage Recommendation |
|---|---|---|
| PLA | Low | Sealed bag with desiccant when not in use |
| PETG | Medium | Sealed bag with desiccant; dry before use if stored open for weeks |
| TPU | High | Always store sealed; dry in oven at 65°C for 4–6 hours if moisture-absorbed |
| ABS | Medium | Sealed 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
| Property | PLA | PETG | ABS | TPU |
|---|---|---|---|---|
| Nozzle temp (°C) | 200–220 | 235–250 | 240–260 | 220–240 |
| Bed temp (°C) | 20–60 | 70–90 | 100–110 | 20–60 |
| Strength | Moderate | High | Very High | Low (flexible) |
| Flexibility | None | Slight | Slight | High |
| Ease of printing | Very Easy | Easy | Hard | Moderate |
| Cost ($/kg) | $15–25 | $20–30 | $18–28 | $30–50 |
| Print speed | 40–60 mm/s | 30–50 mm/s | 20–40 mm/s | 10–30 mm/s |
| Bed adhesion | Easy | Moderate | Requires prep | Easy |
| UV resistance | Low | Moderate | High | Low |
| Chemical resistance | No | Moderate | Yes | No |
Heat Resistance After Printing
This is one of the most common reasons to choose a material other than PLA.
| Material | Safe to use up to | Softens at | Notes |
|---|---|---|---|
| PLA | ~50–60°C | ~60–70°C | Not suitable for car interiors or items near heat sources |
| PETG | ~80–100°C | ~100–110°C | Handles warm environments well |
| ABS | ~90–110°C | ~110–120°C | Good heat resistance; most demanding to print |
| TPU | ~60–80°C | ~80–100°C | Limited heat resistance despite flex durability |
Chemical Resistance
| Material | Water | Alcohol | Acetone | Oils | Acids |
|---|---|---|---|---|---|
| PLA | Low | Low | Dissolves | Low | Low |
| PETG | High | Moderate | Moderate | High | Moderate |
| ABS | High | Moderate | Dissolves | High | Moderate |
| TPU | Moderate | Low | Low | Moderate | Low |
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 Printing | Approximate Strength |
|---|---|
| 0–24 hours | 70–80% of final strength |
| 24–48 hours | 90–95% of final strength |
| 48–72 hours | ~99% of final strength |
| 7+ days | Maximum strength |
Do not stress-test functional parts immediately after printing. Allow at least 24 hours before load testing.
Storage Conditions
| Factor | Recommended Range |
|---|---|
| Storage temperature | 15–25°C |
| Relative humidity | 30–50% |
| Light exposure | Away from direct sunlight |
| Container | Sealed with desiccant packets |
Quick Material Selection Guide
| Question | Answer |
|---|---|
| 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
| Field | Value |
|---|---|
| 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
| Date | Type | Description | Time Spent | Issues Found | Resolution | By |
|---|---|---|---|---|---|---|
Types: Routine / Repair / Calibration / Cleaning / Part replacement
Issue Tracking Log
| Date | Symptom | Diagnosis | Action Taken | Status | Notes |
|---|---|---|---|---|---|
Statuses: Open / In progress / Resolved / Monitoring
Parts Replacement Record
| Date | Part Replaced | Reason | Supplier | Cost | Notes |
|---|---|---|---|---|---|
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.
| Filament | Brand | Nozzle Temp | Bed Temp | Speed | Success Rate | Notes |
|---|---|---|---|---|---|---|
| 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
| Month | Print Success Rate | Common Issues | Overall 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
3dmcommand 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:
| Command | What It Does | Output |
|---|---|---|
3dm build | Compiles .scad source → .stl geometry | build/main.stl |
3dm info | Reports dimensions and AI description | Console text |
3dm preview | Renders model to an image file | build/preview.png |
3dm orient | AI-suggested print orientation | Console text recommendation |
3dm slice | Calls your slicer on the current STL | G-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 ArialLiberation Mono— monospaced, excellent for part numbers and codeDejaVu 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 familyin 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.65tosize × 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)
- What does
3dm orientoutput and when would you use it? - What is the difference between embossed text and debossed (engraved) text in 3D printing? How does the OpenSCAD code differ?
- What does the
sizeparameter intext()represent specifically? Is it the total height of the text block? - What parameter in
text()controls horizontal alignment, and what are the three main options? - What does
str("PART-", 2024, "-", 1)return? - What does
len("OpenSCAD")return? - What is the purpose of
let()in OpenSCAD, and how does it differ from declaring a global variable? - What does setting
$fn=4do to letters rendered withtext()? - What does
3dm previewproduce and where does the output file go? - What is the format for specifying a font style (e.g., bold) in OpenSCAD’s
font=parameter? - 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? - What does
substr("BATCH-001", 6, 3)return? - What happens if you use
text()without wrapping it inlinear_extrude()? - 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 everytext()call? - 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)
- 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.
- Create a dynamic version stamp: use
str()to combine a product name, major version, and minor version, all as separate parameters. - Design a 4-up label sheet: four identical labels in a 2×2 grid, using
translate()and aforloop with two variables. - Build a two-line label: stack two
text()calls at different heights. Line 1 is the label text; line 2 is a smaller subtitle. - Create a label with a decorative border: use
difference()to cut a framing slot into the top face of the label plate. - Use
3dm orienton three different models (a flat slab, a tall cylinder, an L-bracket) and document whether you agree with the AI suggestion in each case. - Build a “batch tag” system: a module that generates 12 small tags in a row, each with a different serial number from a list.
- Design a keychain tag: a rounded rectangle with a ring hole, parametric text, and a border around the text.
- 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. - Build a “negative space” text plate: a plate with all letters cut completely through, creating a stencil or silhouette effect.
- Design a parametric drawer label holder: a clip that attaches to the front edge of a drawer and holds a flat label insert.
- 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.
- Write a screen-reader accessibility guide for the five
3dmcommands. For each command: what it does, expected output, and how to interpret that output without visual reference. - 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.
- 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
-
Create
keychain.scadwith 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. -
Implement text using
linear_extrude()of a 2Dtext()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. -
Produce three size variants — small (25 mm wide), medium (35 mm wide), large (45 mm wide) — by changing only
tag_wandtag_hproportionally. Export an STL for each and record print time and filament weight. -
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
- How did you use OpenSCAD parameters to enable customization without requiring users to edit code logic?
- What were the key differences in print time and material usage between your three size variants?
- 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.
| Variable | Default Value | Unit | Purpose / 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.
| Variant | tag_w (mm) | tag_h (mm) | text_size (mm) | Est. print time | Est. filament (g) |
|---|---|---|---|---|---|
| Small | |||||
| Medium | |||||
| Large |
Print Settings Used
| Setting | Value | Notes |
|---|---|---|
| Layer height | ||
| Infill | ||
| Supports | Yes / No | |
| Nozzle temperature | °C | |
| Bed temperature | °C | |
| Material |
Key Ring Attachment Test
| Test | Result |
|---|---|
| Ring diameter tested | mm |
| Did ring fit through attachment loop? | Yes / No / Tight |
| Does the loop survive a firm tug? | Yes / No |
| Wall thickness at attachment point | mm |
| Any deformation or cracking observed? |
Adjustments needed based on testing:
Print and Assembly Results
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:
- To change the name: set
name = "YOUR TEXT"at line ___. - To change the size: adjust
tag_wandtag_hproportionally. Recommended ratio:tag_h = tag_w * 0.57. - To change the font: update the
LABEL_FONTconstant at line ___. - Common customizations:
- Smaller text that doesn’t overflow: reduce
text_sizeuntil the preview looks right. - Different ring size: change
ring_dto match your key ring’s wire diameter + 1 mm clearance.
- Smaller text that doesn’t overflow: reduce
Reflections
-
Which parameterization decision had the most impact on the usefulness of the final design?
-
How could someone who doesn’t know OpenSCAD still customize this design? What instructions would you write for them?
-
What would you add in a future iteration — a second line of text, a logo, a different attachment style?
Attachments Checklist
-
.scadfile 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
| Category | Score (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)
Recommended Settings by Use Case
| Use Case | Layer Height | Infill | Supports | Notes |
|---|---|---|---|---|
| Quick test / prototype | 0.30 mm | 10% | As needed | Draft — fastest, roughest |
| Standard project | 0.20 mm | 15–20% | As needed | Best all-around starting point |
| Functional part | 0.20 mm | 30–40% | As needed | Use for parts under stress |
| Fine detail / display | 0.15 mm | 15% | As needed | Smoother surface; slower |
| Solid reference part | 0.20 mm | 40–50% | Rarely | Rarely needed; long print |
Filament Temperature Settings
| Filament | Nozzle Temp | Bed Temp | Notes |
|---|---|---|---|
| PLA | 200–215°C | 50–60°C | Easiest to print; default choice |
| PETG | 230–250°C | 70–85°C | Use glue stick on PEI bed |
| TPU | 220–240°C | 30–60°C | Print at 20–30 mm/s max; direct drive only |
| ABS | 230–250°C | 90–110°C | Requires enclosure; ventilate the room |
Always check the temperature range printed on your filament spool — it varies by brand.
Support Settings Guide
| Overhang Angle | Supports Needed? | Recommendation |
|---|---|---|
| < 45° | No | None |
| 45–60° | Maybe | Preview first; add if sagging |
| > 60° | Yes | Support on build plate only |
| Bridge < 20 mm | No | Bridges usually fine |
| Bridge > 20 mm | Maybe | Preview; consider reorienting |
Common Problems and Quick Fixes
| Problem | Likely Cause | Fix |
|---|---|---|
| Print lifts off bed | Poor adhesion / warping | Add brim; use glue stick; re-level bed |
| Stringing between parts | Temp too high / retraction | Lower temp 5°C; check retraction settings |
| Layer lines very visible | Layer height too thick | Use 0.15 mm or 0.20 mm |
| Print takes too long | Layer height too thin / infill too high | Use 0.30 mm draft; reduce infill |
| Holes too small | FDM tolerance — always undersized | Add 0.2–0.3 mm to hole diameter |
| Part broke at layer boundary | Load perpendicular to layers | Reorient so load is parallel to layers |
| First layer not sticking | Bed not level | Run bed leveling routine |
| Spaghetti / print failure | Overhang without supports | Add 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
Recommended Settings by Use Case
| Use Case | Layer Height | Infill | Supports | Notes |
|---|---|---|---|---|
| Quick test / prototype | 0.30 mm | 10% | As needed | Draft — fastest, roughest |
| Standard project | 0.20 mm | 15–20% | As needed | Best all-around starting point |
| Functional part | 0.20 mm | 30–40% | As needed | Use for parts under stress |
| Fine detail / display | 0.15 mm | 15% | As needed | Smoother surface; slower |
| Solid reference part | 0.20 mm | 40–50% | Rarely | Rarely needed; long print |
Filament Temperature Settings
| Filament | Nozzle Temp | Bed Temp | Notes |
|---|---|---|---|
| PLA | 200–210°C | 50–60°C | Easiest to print; Anycubic default |
| PETG | 230–240°C | 70–80°C | Use painter’s tape on steel bed |
| TPU | 220–235°C | 30–50°C | Reduce speed to 25–30 mm/s |
| ABS | 240–250°C | 100–110°C | Requires ventilation; enclosed chamber recommended |
Support Settings Guide
| Overhang Angle | Supports Needed? | Recommendation |
|---|---|---|
| < 45° | No | None |
| 45–60° | Maybe | Preview first; add if sagging |
| > 60° | Yes | Tree supports (Cura) — easier to remove |
| Bridge < 20 mm | No | Bridges usually fine |
| Bridge > 20 mm | Maybe | Preview; consider reorienting |
Common Problems and Quick Fixes
| Problem | Likely Cause | Fix |
|---|---|---|
| Print not adhering to steel bed | Poor leveling / worn tape | Re-level; refresh painter’s tape |
| Filament oozing on travel | Temperature too high | Lower temp 5°C; check Z-hop setting |
| Rough bottom layer | Bed too close | Adjust leveling knob |
| Holes too small | FDM tolerance — always undersized | Add 0.2–0.3 mm to hole diameter |
| Part broke at layer boundary | Load perpendicular to layers | Reorient so load is parallel to layers |
| Clogs at nozzle | Moisture in filament / debris | Dry filament; clear nozzle with needle |
| Spaghetti / complete failure | Bed not leveled or supports missed | Re-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
Recommended Settings by Use Case
| Use Case | Layer Height | Infill | Supports | Notes |
|---|---|---|---|---|
| Quick test / prototype | 0.30 mm | 10% | As needed | Draft — use Standard mode |
| Standard project | 0.20 mm | 15–20% | As needed | Best all-around; Bambu default-optimized |
| Functional part | 0.20 mm | 30–40% | As needed | Use for load-bearing parts |
| Fine detail / display | 0.15 mm | 15% | As needed | Bambu achieves excellent detail at speed |
| Solid reference part | 0.20 mm | 40–50% | Rarely | Modern infill usually sufficient |
Filament Temperature Settings
| Filament | Nozzle Temp | Bed Temp | Notes |
|---|---|---|---|
| PLA (standard) | 200–210°C | 50–60°C | Fastest print times; Bambu-optimized profiles |
| PETG | 230–250°C | 70–80°C | Slight cooling fan reduction for layer adhesion |
| TPU | 220–240°C | 20–30°C | Best quality with Bambu’s tuned retraction |
| ABS | 240–260°C | 100–110°C | Requires chamber heating; enclosed AMS recommended |
Check Bambu’s material database for current profile updates — these are dynamically optimized.
Support Settings Guide
| Overhang Angle | Supports Needed? | Recommendation |
|---|---|---|
| < 45° | No | None |
| 45–60° | Maybe | Auto-supports may activate; accept defaults |
| > 60° | Yes | Bambu auto-tree supports; minimal removal effort |
| Bridge < 20 mm | No | Excellent bridging on Bambu — no supports needed |
| Bridge > 20 mm | Maybe | Often bridgeable; preview before confirming |
Common Problems and Quick Fixes
| Problem | Likely Cause | Fix |
|---|---|---|
| Nozzle clogging mid-print | Thermal runaway / wet filament | Dry filament in AMS; check nozzle temp |
| Layer splitting | Wrong material in AMS slot | Verify correct material in Bambu Studio |
| Stringing / blobbing | Cooling fan too low | Increase cooling; adjust material profile |
| Print lifts off bed | Bed leveling drift (rare on Bambu) | Auto-calibrate via Bambu Studio |
| Holes undersized | FDM tolerance — always undersized | Add 0.3–0.4 mm to hole diameter |
| Part broke at layer boundary | Load perpendicular to layers | Reorient so load is parallel to layers |
| Print aborts unexpectedly | AMS issue / filament jam | Clear AMS; verify filament path |
| Multi-material print misaligned | Nozzle offset miscalibration | Run 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(), andscale()in the correct order for compound transforms - Use trigonometric functions (
sin(),cos(),atan2()) to compute precise geometry positions - Use
minkowski()to create rounded edges andmirror()to create perfectly symmetric parts - Build a complete parametric phone stand from three measured dimensions
- Use
$previewto 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) * ry = 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)
- In OpenSCAD, do transforms apply left-to-right or right-to-left (which transform runs first)?
- What is the result of
cos(0)andsin(90)in OpenSCAD (working in degrees)? - What is the key advantage of
atan2(y, x)overatan(y/x)for computing angles? - What does
minkowski()do geometrically? Describe it in plain language. - What does
mirror([1, 0, 0])do? Which plane does it reflect across? - What does
scale([1, 1, 2])do to a sphere? - Write OpenSCAD code to place 8 cylinders evenly spaced around a circle of radius 30 mm.
- What does
norm([3, 4, 0])return, and how is this computed? - True or False:
translate([10,0,0]) rotate([0,0,45]) cube(5)rotates the cube first, then translates it. - What does setting
$previewtotruemean in OpenSCAD, and when is it set automatically? - Why does using
minkowski()withcylinder(h=0.01)instead ofsphere()produce a flat bottom surface? - In the phone stand design, the back support uses
rotate([angle - 90, 0, 0]). Ifangle = 70, what is the actual rotation applied? What does this mean physically? - What does
cross([1,0,0], [0,1,0])return and what is the geometric meaning? - Explain why designing one half of a symmetric part and using
mirror()is better than designing both halves separately. - A design requires placing 5 components at the vertices of a regular pentagon centered at the origin. Using
cos()andsin(), what is the formula for the coordinates of each vertex, given a circumradius of 25 mm?
Extension Problems (15)
- Redesign your phone stand with a USB cable slot cut through the lip. Make the slot width and depth parameters.
- Add rubber foot pockets to the base plate: four small rectangular cutouts on the bottom face, positioned at the corners.
- Create a phone stand variant that holds the phone in landscape (horizontal) orientation. Document which parameters changed and why.
- Build a radially symmetric decoration: 12 identical fins evenly spaced around a central cylinder using
forloop androtate(). - Use
atan2()to compute the angle of a ramp and use that angle withrotate()to align a small object precisely on the ramp surface. - 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.
- 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.
- Create an ergonomic keyboard wrist rest using
minkowski()with a cylinder for smooth, flat-base contouring. - Build a visual transform order demo: two colored objects that differ only in the order of
translate()androtate(), placed side by side with labels. - Redesign the phone stand as a wall-mount: replace the base plate with a flat back plate that has two M3 mounting holes.
- 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. - 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. - 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. - 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.
- Design a dual phone stand: two cradles side by side at different angles, sharing a common base. Use a
forloop 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
- Programming with OpenSCAD EPUB Textbook — Transforms chapter
- CodeSolutions Repository — Phone stand worked example
- OpenSCAD Quick Reference — Math and transform functions -e
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 Type | Clearance (typical PLA, 0.4mm nozzle) | Behavior |
|---|---|---|
| Press-fit (permanent) | 0.0 – 0.1 mm | Requires force to assemble; doesn’t come apart easily |
| Slip-fit (removable) | 0.2 – 0.3 mm | Slides smoothly; can be assembled and disassembled by hand |
| Loose/clearance fit | 0.4 – 0.5 mm | Some 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
Print This Before Every New Printer or Material
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 Type | Test Method | What to Record |
|---|---|---|
| Press-fit | Tightest peg that enters socket with firm thumb pressure | Your press clearance |
| Slip-fit | Loosest peg that doesn’t rattle in the socket when shaken | Your slip clearance |
| Bearing/pivot | Loosest peg that rotates smoothly without visible wobble | Slip + 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):
| Material | Maximum beam_t / beam_l | Why |
|---|---|---|
| PLA | 0.15 | Relatively stiff; snaps or cracks if over-flexed |
| PETG | 0.18 | Slightly more flexible than PLA |
| Nylon | 0.20 | Good flexibility and fatigue resistance |
| TPU | 0.25 | Very flexible; excellent for repeated flex |
| ABS | 0.12 | More 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)
- Why do FDM-printed holes consistently come out smaller than designed? Explain the physical mechanism.
- What clearance range (in mm) produces a slip-fit for a typical FDM printer with a 0.4mm nozzle and PLA?
- What is a press-fit, and what application would you use one for?
- What is the beam_t / beam_l flexibility rule for PLA snap-fit cantilever beams?
- Why must you print a tolerance test coupon rather than using published clearance values from a chart?
- What is a heat-set threaded insert and why is it preferred over a plastic-tapped hole for assemblies that are disassembled repeatedly?
- What is a dovetail joint and in which direction does it lock?
- What does a stacking lip do in a stackable bin design, and how does clearance factor into its dimensions?
- True or False: a thicker snap-fit beam is easier to deflect than a thinner one of the same length.
- What happens if you design a stacking lip with clearance = 0mm?
- 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?
- Why should tolerance clearance values be defined as named constants at the top of a file rather than hardcoded at each use?
- Describe how a chamfer is created using
difference(). What shape is subtracted from the original? - For a snap-fit clip made of PLA with
beam_l = 18mm, what is the maximumbeam_tallowed by the flexibility rule? Show your calculation. - 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)
- Design a complete stackable bin set (small, medium, large) where each size nests inside the next. Use your measured tolerance values throughout.
- 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(). - 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.
- Create a wall-mount organizer using snap-fit clips that attach to a standard pegboard (hole pitch = 25.4mm, hole diameter = 6.35mm).
- Build a two-part enclosure with heat-set insert pockets for M3 screws and matching through-holes for the bolts. Test with real hardware.
- Design a snap-together dice tray: the tray snaps into a carrying case lid using four snap clips.
- 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.
- Build a cable management clip with a snap-fit that can be opened and closed repeatedly for easy cable insertion and removal.
- Design a telescoping tube: an inner cylinder that slides freely inside an outer cylinder using your measured slip-fit clearance.
- Create a bayonet mount: a part that locks with a 90° twist.
- 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.
- Build a parametric drawer divider system: interlocking slotted panels that can be arranged in any grid configuration.
- Design a self-locking dovetail joint that slides together in one direction and resists being pulled apart in any perpendicular direction.
- 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.
- 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
-
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.
-
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).
-
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.
-
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
.scadfile 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
- What clip thickness and spacing values produced a reliable snap-fit for your specific printer and material?
- How did you balance flexibility (easy to snap and unsnap) with durability (no premature failure)?
- 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
| Parameter | Nominal 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.
| Variant | Tolerance (mm) | Assembly effort | Disassembly effort | Deformation after 5 cycles | Pass / 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:
-
Describe the snap mechanism — explain why it works mechanically, not just that it does.
-
What material properties enable this design? What would happen if you printed the same geometry in a rigid material with no flex (like resin)?
-
Where are the stress concentration points in your design? How did you address them?
Reflections
-
Did the snap-fit work as expected on the first print? If not, what surprised you?
-
What tolerance adjustment had the most significant effect, and by how much?
-
How would you modify this design for a clip that needs to work at outdoor temperatures (hot car in summer, cold winter)?
-
What materials would fail with this exact geometry? Why?
Attachments Checklist
-
.scadfile 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
| Category | Score (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 -Dfrom 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:
- Open terminal
- Type the command with the right parameter values
- Wait for OpenSCAD to render
- Check that the output exists
- Rename the file so it doesn’t overwrite the last one
- 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
.scadfiles, 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)
- What does
set -edo in a bash script? - Why is passing string parameters with
-Dmore complex than passing numeric parameters? - What does
trap 'on_error $LINENO' ERRdo in a bash script? - What is the correct way to pass
label="FRONT"as an OpenSCAD-Dargument in bash? - What does
set -uprotect against? - How would you verify that an output STL was actually created in a build script?
- What is a “silent failure” in the context of automation, and how do you prevent one?
- In PowerShell, what character is used to escape a double quote inside a double-quoted string?
- What does
$LASTEXITCODEcontain in a PowerShell script after running an external command? - Describe the purpose of a timestamped build archive and when you would use it.
- What is CI/CD, and how does it apply to a 3D printing project workflow?
- True or False: In CMD, doubled double-quotes inside a quoted string produce a single literal double-quote.
- Explain the difference between a poll-based file watcher and an event-based file watcher. What are the trade-offs?
- In a GitHub Actions workflow, what does
on: push: paths: - 'src/**'specify? - 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)
- Write a batch build script that tests 10 parameter combinations and generates a summary report with pass/fail status for each.
- 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.
- Implement the timestamped archive system and add a rotation policy: automatically delete archives older than 30 days.
- Build a Git pre-commit hook that runs
3dm buildand fails the commit if the build doesn’t succeed. - Create a build dashboard: a script that runs all your projects’ builds, collects their
3dm infooutputs, and formats them into a summary report. - Implement parallel builds: run multiple OpenSCAD builds simultaneously using background processes or PowerShell jobs. Measure the speedup.
- Create a “changelog” generator: compare the bounding boxes of all archived builds and generate a list of which builds had dimension changes.
- Write a CI/CD pipeline configuration for GitLab CI or Bitbucket Pipelines (instead of GitHub Actions).
- Build a build notification system: send a Slack message or email when a build fails.
- Create a “test suite” of deliberately bad
.scadfiles (empty geometry, non-manifold shapes, syntax errors) and verify your build script catches all of them. - Implement semantic versioning in your build system: automatically increment a patch version number on each successful build.
- Write a multi-platform build script that detects the current OS and uses the appropriate commands (bash on Linux/macOS, PowerShell on Windows).
- Create a build matrix: for each of 5 designs × 4 materials, build the design with material-specific parameters and verify each output.
- Implement a “regression test”: store the bounding box of each successful build, and flag any build where the bounding box changes unexpectedly.
- 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()andminkowski()with awareness of their performance cost - Use
$previewto 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()andlookup()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=64can take many minutes to render. Always use$previewto skip theminkowski()call during development.
$preview: Fast Development, Accurate Rendering
OpenSCAD has two rendering modes:
- F5 (Preview): Fast, approximate. Uses OpenCSG rendering.
$previewistrue. - F6 (Full Render): Exact, uses CGAL library. Much slower but produces accurate manifold geometry for export.
$previewisfalse.
Use $preview as a conditional: show a fast placeholder during development (F5), and run the expensive minkowski() only during final render (F6).
Version note:
$previewis available in OpenSCAD 2019.05 and later. In earlier versions it is undefined (treated asfalse). If you are using an older version, omit the$previewguard 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 faces | Secondary $fn | Expected render time |
|---|---|---|
| < 100 | 8–16 | < 1 second |
| 100–500 | 8–16 | 1–10 seconds |
| 500–2000 | 8 | 10–60 seconds |
| > 2000 | any | Minutes 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 heightcut=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:
3dmis designed for building STL output. Use theopenscadCLI directly for DXF export — do not use3dm buildfor 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:
- Every edge is shared by exactly two faces — no more, no fewer
- 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.
Step 7 — Advanced: Lookup Tables and search()
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. Checklen(matches[0]) > 0for 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)
- What tool do you use to measure printed part dimensions against the design specification?
- What is tolerance stack-up, and why does it matter for multi-part assemblies?
- What causes non-manifold geometry in OpenSCAD, and how do you detect it?
- How does
hull()differ fromunion()? - What does
3dm infohelp you verify about your model? - What is the diameter of a Cherry MX stem, and what clearance would you add for a slip-fit keycap?
- True or False:
find -neweris an event-driven file change detection method. - If three parts each have ±0.15 mm tolerance, what is the worst-case total error for a three-part stack?
- What does the
$fnparameter control in OpenSCAD? - Describe two methods for fixing non-manifold geometry caused by two touching (but not overlapping) shapes.
- What is the difference between
hull()andminkowski()for creating organic shapes? Give one use case for each. - What does
resize([50, 0, 0])do, and why mightresize()behave unexpectedly for non-uniform scaling? - 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?
- Describe the iterative workflow for dialling in press-fit tolerances: what do you print, what do you measure, and how do you adjust?
- If
3dm inforeports “the model appears non-manifold,” what are three possible causes you would investigate in your OpenSCAD code?
Extension Problems (15)
- 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.
- 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.
- Write a printer calibration SOP: bed levelling, first-layer calibration, and dimension verification. Include a measurement checklist.
- Build a three-tier stackable storage system for art supplies. Each tier has a different inner grid.
- Conduct a tolerance stack-up analysis for your stackable bin system. Calculate worst-case misalignment.
- Build a parametric test coupon that tests four wall thicknesses (0.8, 1.2, 1.6, 2.0 mm) in a single print.
- Design a caliper stand: a holder that keeps your digital calipers at a comfortable angle for one-handed operation.
- 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.
- Use
hull()to design a smooth ergonomic tool handle and compare it to a simple cylinder handle. - Create a printability checklist for new designs: overhangs, wall thickness, minimum feature size, support requirements. Apply it to your keycap and bin designs.
- Research the
resize()function. Build an example showing how it behaves differently fromscale()for non-uniform resizing. - Design a multi-part assembly tutorial: a three-piece interlocking puzzle that teaches tolerance, alignment, and slip-fit.
- 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.
- 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.
- 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
- Measure each feature three times and record all three values.
- Calculate the average: add the three values and divide by 3.
- Round to one decimal place (e.g., 23.4 mm).
- Use the average in your OpenSCAD code — not any single measurement.
Units: All measurements in millimeters (mm) unless otherwise noted.
Object 1
Object description: ________________
| Feature | What You’re Measuring | M1 (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: ________________
| Feature | What You’re Measuring | M1 (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: ________________
| Feature | What You’re Measuring | M1 (mm) | M2 (mm) | M3 (mm) | Average (mm) |
|---|---|---|---|---|---|
| Length (X) | |||||
| Width (Y) | |||||
| Height (Z) | |||||
| Feature 4 | |||||
| Feature 5 |
Object 4
Object description: ________________
| Feature | What You’re Measuring | M1 (mm) | M2 (mm) | M3 (mm) | Average (mm) |
|---|---|---|---|---|---|
| Length (X) | |||||
| Width (Y) | |||||
| Height (Z) | |||||
| Feature 4 | |||||
| Feature 5 |
Object 5
Object description: ________________
| Feature | What You’re Measuring | M1 (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.
| Object | My 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
| Object | Your Average | True Value | Difference | % Error |
|---|---|---|---|---|
A percent error under 2% is excellent for caliper work at this level.
Reflection
Answer in complete sentences.
-
Which measurement was most difficult to take and why?
-
Did your three measurements for any feature vary significantly? What might cause that variation?
-
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:
- Heat extruder to printing temperature.
- Mark filament 100 mm from the extruder entrance with a marker.
- Command extrusion of exactly 100 mm (
G1 E100 F100). - 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
| Material | Typical Shrinkage | Recommended Action |
|---|---|---|
| PLA | 0.3–0.5% | Usually acceptable; no action needed |
| PETG | 0.5–1% | Scale design up 0.5–1% for critical dimensions |
| ABS | 0.8–1.5% | Scale up 1% minimum |
| TPU | 1–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
| Measurement | Method | Acceptable Tolerance | Frequency |
|---|---|---|---|
| Wall thickness | Calipers (3 spots) | ±0.1 mm | Every print |
| Hole diameter | Calipers or gauge | ±0.1–0.2 mm | Every print |
| Overall dimensions | Calipers | ±0.2 mm | Monthly |
| Layer height | Stack on calipers | ±0.02 mm | Monthly |
| Vertical height | Measure side face | ±0.1 mm | Every 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
Recommended Measurement Tools
| Tool | Typical Cost | Accuracy | Best Use |
|---|---|---|---|
| Digital calipers | $5–15 | ±0.05 mm | Primary tool for all work |
| Steel ruler | $3–10 | ±1 mm | Quick rough checks |
| Vernier calipers | $10–30 | ±0.05 mm | Precision work |
| Micrometer | $20–50 | ±0.01 mm | Critical 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
| Field | Value |
|---|---|
| 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.
| Range | Assessment |
|---|---|
| ±2°C | Excellent |
| ±5°C | Acceptable |
| ±10°C | Marginal — investigate thermal sensor |
| >±10°C | Problem — do not print until resolved |
C — Mechanical Systems
Disable motors (if firmware allows) and manually move each axis. Expected: smooth, no grinding.
| Axis | Result |
|---|---|
| X-axis | smooth / rough / stuck |
| Y-axis | smooth / rough / stuck |
| Z-axis | smooth / 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)
- Heat bed and nozzle to printing temperature.
- Move nozzle to each corner; adjust leveling screw until a standard sheet of paper drags slightly under the nozzle.
- Repeat for all 4 corners, then check center.
- 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
| Appearance | Cause | Fix |
|---|---|---|
| Wavy / embossed lines | Nozzle too close to bed | Raise Z-offset |
| Gaps between lines | Nozzle too far from bed | Lower Z-offset |
| Completely squished flat | Nozzle too low or bed too high | Raise Z-offset or re-level |
| Partial adhesion only | Bed too cool or dirty | Clean bed; increase bed temperature |
| Consistent, even lines | Correct | Continue print |
Mid-Print Extrusion Failure
When extrusion stops during a print:
- Pause (do not cancel) immediately.
- Listen for extruder grinding sounds (indicates jam).
- 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:
- Measure each dimension 3 times at different locations.
- Calculate average.
- Compare to the design dimension.
- Calculate deviation:
Deviation % = ((Measured − Design) / Design) × 100%
| Tolerance | Status | Action |
|---|---|---|
| ±0.5 mm or better | PASS | No adjustment needed |
| ±0.5–1 mm | MARGINAL | Document and monitor |
| >±1 mm | FAIL | Adjust 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):
- Increase nozzle temperature by 10°C — too cold makes extrusion harder.
- Clean the extruder drive gear with a wire brush to restore grip.
- Check filament diameter — should be 1.75 mm ±0.03 mm. A spool that measured correctly when new may have inconsistent sections.
- Verify extruder tension — should grip firmly but not crush the filament.
- 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:
- Cut off ~30 cm of the damaged section and discard.
- 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.
- Store filament sealed with desiccant between sessions — especially important for Nylon, PETG, and TPU, which are hygroscopic.
Print Quality Issues
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):
- Re-level the build plate — cold plate leveling is more accurate.
- Clean the build plate — wipe with isopropyl alcohol to remove oils and dust.
- Lower the nozzle — if it’s too high, reduce Z-offset by 0.05–0.1 mm.
- Increase bed temperature by 5–10°C.
- 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):
-
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.
-
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.
-
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.
-
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:
- Check for partial nozzle clog (a fully extruding nozzle means a partial clog is possible).
- Increase flow rate by 5–10% in the slicer.
- Raise temperature by 5–10°C.
- Reduce print speed by 10–20%.
- Calibrate E-steps (see Appendix B).
- 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:
- Reduce flow rate to 95% in the slicer.
- Lower temperature by 5–10°C.
- Verify line width — should be approximately 1.2× the nozzle diameter (0.4 mm nozzle → 0.48 mm line width).
- 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:
- Check mechanics: manually move X/Y (motors disabled) — should feel smooth, no resistance. Tighten all visible screws. Inspect belts for fraying.
- Reduce travel speed by 20–30%. Reduce acceleration in firmware.
- Check print orientation — tall, thin prints are vulnerable to the nozzle catching an edge and shifting. Rotate or add a brim.
- 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:
- Reduce temperature by 5–10°C.
- Increase retraction distance by 0.5–1.5 mm.
- Increase retraction speed.
- Enable “wipe on retract” in slicer.
- 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
| Issue | Prevention | Frequency |
|---|---|---|
| Clogs | Clean nozzle; avoid heat-creep by maintaining cooling fan | Before each print |
| Bed adhesion | Level bed; clean plate with IPA | Before each print |
| Layer shift | Check belt tension and drive gear screws | Monthly |
| Inconsistent quality | Calibrate E-steps; standardize environment | Quarterly |
| Worn nozzle | Monitor extrusion quality; replace on schedule | Every 6 months |
| Moisture in filament | Store sealed with desiccant | Ongoing |
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
- Select one lesson or project (an OpenSCAD file plus its markdown instructions) and review it for accessibility shortcomings.
- Create a checklist covering: image alt-text, code walkthroughs, tactile cues, plain-language explanations, and file naming conventions. Apply it to the chosen resource.
- Implement at least three small improvements (add alt text, improve code comments, write a text-only step-by-step walkthrough) and document every change.
- 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:
| Recommendation | Priority (H/M/L) | Feasibility (Easy/Med/Hard) | Impact (H/M/L) |
|---|---|---|---|
(Repeat for each resource)
Summary of Barriers Found
| Barrier | Frequency | Severity | Resources Affected |
|---|---|---|---|
Recommendations Matrix
| Priority | Feasibility | Impact | Recommendation | Implementation Steps |
|---|---|---|---|---|
| High | Easy | High | ||
| High | Medium | High | ||
| Medium | Easy | Medium |
Reflection Questions
Answer in complete sentences:
- What surprised you about the accessibility barriers you found?
- How would you prioritize improvements if you had limited time?
- What role should users with disabilities play in accessibility testing, rather than non-disabled designers guessing at barriers?
- 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)
| Category | Score (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:
- Empathize — Interview the user to understand their “pain points.” What do they struggle with? What workarounds do they currently use?
- Define — Create a list of requirements the part must satisfy. Make them specific and testable.
- Ideate — Use your OpenSCAD skills to create a parametric solution that addresses the requirements.
- Prototype & Test — Build the part and have the stakeholder test it with their own hands.
- 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 Question | Open-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 Requirement | Acceptance Criterion |
|---|---|
| Must support weight without tipping | Holds 200 g with center of gravity at the rim; does not tip on a 5° incline |
| Bead hole accommodates 1.5 mm cord | A 1.5 mm test cord passes through with finger pressure; does not fall out under its own weight |
| No sharp edges | A 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
.scadfile 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)andbead_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:
.scadfile containing parametric bead modules and the assembly script.stlfiles (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
scaleparameter 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:
| Category | Max Points | What Is Evaluated |
|---|---|---|
| Implementation & parametric code | 3 | Modules are parametric, well-named, commented; assembly uses variables |
| Functionality & wearability | 3 | Piece is wearable; holes fit cord; no sharp edges; FRs met |
| Documentation & print notes | 2 | Design notes, revision log, FR document, print settings recorded |
| Presentation & photos | 1 | Multiple views; worn photo; alt-text provided |
Quiz — Option A: Beaded Jewelry (15 questions)
- Why use parametric modules for repeated parts rather than copying geometry? (one sentence)
- What is a reliable way to test a bead hole size for a given cord diameter before printing the full set?
- Name two OpenSCAD features or techniques useful for repeating geometry across a pattern.
- What print setting is most likely to affect hole diameter accuracy in FDM printing?
- How would you document an iteration that changed hole diameter from 2.5 mm to 2.7 mm?
- True or False: Once your first bead prints successfully, all subsequent iterations will print exactly the same.
- Explain what “wearability” means for a jewelry design. Name two specific checks you would perform to confirm a necklace is comfortable.
- Your bead design uses a 3 mm hole. When strung on cord, it’s too tight to slide. What are two OpenSCAD-level solutions?
- 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?
- Why does the Stakeholder Interview happen before you write any code?
- Write a User Story for the following requirement: the cord hole must accommodate a 1.5 mm nylon cord.
- What is an Acceptance Criterion, and how does it differ from a Functional Requirement?
- You receive feedback that the beads “feel scratchy.” Describe the engineering process for investigating and fixing this — do not just say “sand them.”
- What is the
hull()function useful for in bead design? Give one specific example. - 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)
- Design an interlocking bead (snap-fit connection between beads) and document the clearances required.
- Create a parametric clasp module that integrates with your bead string and includes a documented pass/fail test.
- Modify one bead to include decorative text or a pattern generated procedurally in OpenSCAD.
- Convert your single
.scadproject into a small library: separate bead modules intouse-able include files and demonstrate reuse. - Propose a modification to make the piece weather-resistant for outdoor wear (materials, coatings, or geometry changes). Justify each choice.
- Design and print a complete jewelry set: matching beads, clasp, and string connector with a consistent design language.
- Create a variant generator that produces 10+ different bead designs from single-parameter changes. Document aesthetic and functional differences.
- Build a design system document for your jewelry: modular bead library, material requirements, assembly instructions, and care guide.
- Investigate material effects: print the same bead in two or more materials. Compare durability, aesthetics, and wearability with measurements.
- Develop a parametric customization guide: enable another person to modify size, spacing, and aesthetics through top-level variables alone.
- 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.
- 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.
- Use
surface()orminkowski()to add a texture to your bead surface. Document the performance impact and the$previewguard you used. - Write a batch build script that exports STLs for 8 bead variants (different sizes or shapes) automatically, with timestamped output names.
- 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.
| Dimension | Description | Nominal (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
| Part | Material | Est. print time | Est. 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
| Component | Version | Print date | Key measurements | Pass/Fail | Issues 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:
- What you changed and why (reference a specific failure mode)
- What you printed (component name, version, parameters used)
- How you tested it (specific test — not just “I tried it”)
- What you measured (calipers, fit test, load test)
- What you concluded (did the change fix the problem? Create new ones?)
- 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()orminkowski()for organic shapingsurface()for textured or embossed panelschildren()container modulesearch()orlookup()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
| Part | File / Source | Material | Print Settings | Est. Time | Est. 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.
| Criterion | 1 — Beginning | 2 — Developing | 3 — Proficient | 4 — Exemplary |
|---|---|---|---|---|
| Parametric Design | Hardcoded dimensions; no variables | Some variables; not all key dimensions | All key dimensions parametric; named clearly | Fully parametric; changing one variable produces a valid design at any scale |
| CSG Modeling | Primitives only; no CSG | CSG used but with co-planar artifacts | CSG correct; 0.001 offsets applied | No non-manifold geometry; CSG used for all complex shapes |
| Tolerance & Fit | No tolerance consideration; parts don’t fit | Tolerances guessed; some parts fit | Tolerances measured and calibrated; all parts fit | Test coupon printed; stack-up calculated; all fits confirmed |
| Interlocking Features | None | One feature, poorly fit | One feature, well-designed and functional | Two or more features; each type chosen appropriately |
| Build Automation | No build script | Script builds but no error handling | Script builds, verifies, and archives | Handles all platforms; batch variants supported |
| Documentation | README missing or minimal | README present but incomplete | README covers all required sections | README enables a stranger to reproduce the design from scratch |
| Iteration | No documented revisions | 1–2 revisions, partially documented | 3 revisions, fully documented with rationale | 4+ revisions; each driven by measured test data |
| Advanced Features | None | One feature present | One feature well-integrated | Two or more; each justified in documentation |
| Reflection | Superficial or missing | Present but generic | Genuine reflection on specific challenges | Insightful; 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)
- What is a stakeholder, and why is identifying stakeholders the first step in a design project?
- What is the difference between a Maker and a Design Professional, as described in this lesson?
- Why are open-ended interview questions preferred over yes/no questions?
- Write a complete User Story for this requirement: “The lid must be openable with one hand.”
- What are Acceptance Criteria, and how do they make a Functional Requirement testable?
- How does a Design Specification bridge requirements and OpenSCAD code? Give an example.
- True or False: Design Thinking is a linear process that ends after the first prototype.
- Why should you never adjust a design based on vague feedback like “it feels too tight” without first taking measurements?
- How can
3dm infoinvolve a stakeholder who cannot see the 3D model visually? - 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?
- What is tolerance stack-up, and why does it become critical in Phase 1 rather than something to fix later?
- Describe the purpose of printing a tolerance test coupon before printing a full assembly.
- What should a revision log entry contain? Write an example entry for a wall thickness change.
- Your build automation script reports that one STL is 340 bytes. What does this likely indicate, and what do you do next?
- 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)
- Conduct a full tolerance stack-up analysis for your assembly. Calculate worst-case misalignment across all interfaces.
- Design a go/no-go gauge for your most critical fit — a test part that passes only when the tolerance is correct.
- Write a multi-platform build script that detects the OS and uses the appropriate shell commands automatically.
- Implement semantic versioning in your build system: automatically increment a patch version on each successful build.
- Build a Git pre-commit hook that runs your build script and refuses the commit if the build fails.
- 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.
- Design a three-part interlocking system where all parts can be assembled in only one correct order. Document the design intent.
- Write a GitHub Actions CI/CD workflow that builds all components on every push to the
mainbranch and uploads STL artifacts. - Implement
lookup()tables for material-specific parameters (density, clearance, recommended wall thickness). Make switching materials a one-variable change. - Produce a full DXF drilling template using
projection()for any part of your design that requires holes in a non-printed substrate. - Build a “measurement worksheet” that renders in OpenSCAD as a flat printed sheet listing all key dimensions — print it alongside your prototype.
- 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.
- 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.
- Redesign your most complex module to use
children()as a container pattern, then demonstrate it with three different child geometries. - 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)
| Week | Checkpoint | What to Show |
|---|---|---|
| End of Week 1 | Phase 1 complete | Interview notes, problem statement, measurement worksheet, FRs, design spec, sketch, BOM, risk assessment |
| End of Week 2 | First print | At least one component printed and tested; Phase 2 test log started |
| End of Week 3 | Three revisions | Phase 3 cycles 1–3 documented; feedback session complete; build script working |
| End of Week 4 | Feature complete | All components printing and fitting; advanced feature implemented |
| End of Week 5 | Documentation draft | README draft; STL files exported; reflection drafted |
| End of Week 6 | Final submission | All 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
-
clearanceconstant 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
| Field | Your 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)
-
“Tell me about your role and how this design would fit into your life.”
- Notes:
-
“What problem are we trying to solve together?”
- Notes:
-
“Who else might be affected by this design?”
- Notes:
Section 2: Current Situation (10 minutes)
-
“How do you currently handle this problem — what do you do today?”
- Notes:
-
“What works well about what you do now?”
- Notes:
-
“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.
-
“Ideally, what would a perfect solution do for you?”
- Notes:
-
“Walk me through how you’d use it in a typical situation.”
- Notes:
-
“Where would it live — what space does it need to fit into?”
- Notes:
Constraints heard (fill in as they come up):
| Type | What they said | Design implication |
|---|---|---|
| Physical size | ||
| Weight | ||
| Temperature / environment | ||
| Durability | ||
| Budget | ||
| Timeline |
Section 4: Usage Patterns (10 minutes)
-
“How often would you use this?”
- Daily [ ] Weekly [ ] Monthly [ ] Occasionally
- Notes:
-
“Who else might use it? Are there any accessibility considerations I should know about?”
- Notes:
Section 5: Success Criteria (10 minutes)
-
“If this design worked perfectly, how would you know? What would be different about your day?”
- Notes:
-
“What would make you say this design failed?”
- Notes:
Success Criteria (draft):
Section 6: Priorities (10 minutes)
- “If you could only have three features, which three would matter most to you?”
- (Priority: /10)
- (Priority: /10)
- (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
| Field | Your 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
| Requirement | Test Method | Pass Condition | Status |
|---|---|---|---|
| FR1 | |||
| FR2 | |||
| FR3 |
Template 3: Design Specification
Use this for: Mapping FRs to OpenSCAD parameters before writing code.
Project Information
| Field | Your 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.
| FR | OpenSCAD Variable | Value / Formula | Rationale |
|---|---|---|---|
| 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
| Interface | Type of fit | Nominal dim. | Clearance used | Rationale |
|---|---|---|---|---|
| Part A → Part B | Press / Slip / Loose |
Material Selection
Primary material:
| Property | Requirement | Why this material satisfies it |
|---|---|---|
| Strength | ||
| Flexibility | ||
| Temperature resistance | ||
| Cost |
Risk Register
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| H/M/L | H/M/L | ||
| H/M/L | H/M/L |
Design Change Log
| Version | Date | Change | Reason |
|---|---|---|---|
| 0.1 | Initial design |
Template 4: Feedback Collection
Use this for: Phase 3 — structured feedback session with your stakeholder.
Session Information
| Field | Your 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?):
-
“What is your first reaction to this?”
- Response:
-
“Is it what you expected?”
- More than expected [ ] As expected [ ] Less than expected
- Why:
-
“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):
-
“Was it easy to figure out how to use?”
- Very easy [ ] Easy [ ] Neutral [ ] Difficult [ ] Very difficult
- What was confusing:
-
“Are there any parts that don’t work well together?”
- Response:
Usability Issues Observed:
| Issue | Severity (H/M/L) | Stakeholder’s suggestion |
|---|---|---|
Section 3: Functional Assessment (10 minutes)
Test each Functional Requirement explicitly.
| Requirement | Result | Notes |
|---|---|---|
| FR1: | [ ] Pass [ ] Partial [ ] Fail | |
| FR2: | [ ] Pass [ ] Partial [ ] Fail | |
| FR3: | [ ] Pass [ ] Partial [ ] Fail |
- “What’s missing that you expected to be there?”
- Response:
Section 4: Physical Assessment (10 minutes)
-
Size: [ ] Too large [ ] Just right [ ] Too small
- Notes:
-
Weight: [ ] Too heavy [ ] Just right [ ] Too light
- Notes:
-
“Does the material / finish feel appropriate?”
- Response:
-
“Any parts that feel fragile or rough?”
- Response:
Section 5: Overall Satisfaction (5 minutes)
| Criterion | Score (1–5) | Comments |
|---|---|---|
| Overall satisfaction | ||
| Meets my needs | ||
| Design quality | ||
| Would recommend to someone else |
(1 = Poor, 5 = Excellent)
Section 6: Suggestions (10 minutes)
-
“What one change would have the biggest positive impact?”
- Response:
-
“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 design | Feedback received | Change made | Rationale |
|---|---|---|---|
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:
| Category | Max Points | What Is Evaluated |
|---|---|---|
| Problem & Solution | 3 | How well the prototype meets the identified problem or FRs |
| Design Quality | 3 | Complexity, originality, technical quality; evidence of iteration |
| Documentation | 3 | Completeness, accuracy, and thoughtfulness of all written deliverables |
Category 1: Problem & Solution (0–3 points)
| Score | Description |
|---|---|
| 3 | Prototype clearly and effectively solves the stated problem. All FRs are met. Evidence of testing against requirements. |
| 2 | Prototype mostly meets the problem. Most FRs met. Minor gaps between design and requirements. |
| 1 | Prototype partially addresses the problem. Several FRs unmet or not clearly tested. |
| 0 | Prototype does not address the stated problem, or no FRs were established. |
Category 2: Design Quality (0–3 points)
| Score | Description |
|---|---|
| 3 | Design 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. |
| 2 | Design is functional and shows thought. Code works but may lack structure (few comments, raw numbers). Print quality acceptable. Some iteration evident. |
| 1 | Design is basic or borrowed without modification. Code has issues. Print quality has unaddressed defects. |
| 0 | No meaningful original design. Print is non-functional or not completed. |
Category 3: Documentation (0–3 points)
| Score | Description |
|---|---|
| 3 | All required sections present, complete, and specific. Reflections are thoughtful and reference specific decisions, problems, and learning. Photos included. Measurements recorded. |
| 2 | Most sections present. Some sections vague or missing detail. Reflections show thought but are brief or generic. |
| 1 | Documentation incomplete. Major sections missing or one-line responses. Reflections minimal. |
| 0 | Documentation not submitted or essentially empty. |
Score Interpretation
| Total Score | Interpretation | Next Step |
|---|---|---|
| 8–9 | Excellent work | Move to next project |
| 6–7 | Good work with room for improvement | Move on; instructor may suggest revisiting one element |
| 4–5 | Meets basic expectations | Resubmission of specific weak areas recommended |
| 2–3 | Does not meet expectations | Resubmission required |
| 0–1 | Missing major deliverables | Meet 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. Thelen()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
| Points | Criteria |
|---|---|
| 4 | Correct answer with clear, complete explanation; demonstrates deep understanding |
| 3 | Mostly correct answer; minor gaps in explanation or reasoning |
| 2 | Partially correct; shows some understanding but has significant gaps |
| 1 | Minimal effort; shows limited understanding |
| 0 | No answer or completely incorrect |
Total Possible: 100 + 5 bonus = 105 points
References You May Use
- 3dMake Quick Reference
- OpenSCAD Cheat Sheet
- Appendix A: Comprehensive Slicing Guide
- Appendix C: Tolerance Testing & QA Matrix
- Appendix D: PowerShell Integration
End of Final Exam
Submission Instructions:
- Answer all 25 questions completely
- Show your work for calculations and reasoning
- Include code samples where requested
- Submit as a PDF with your name and date
- 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]);
- Co-planar bottom face — the first cylinder’s base is flush with the cube’s base (
z=0). - Co-planar top face — the second cylinder starts exactly at the cube’s top (
z=25). - 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
forwith 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
| Task | bash (Linux/macOS) | PowerShell (Windows) | CMD (Windows) |
|---|---|---|---|
| Build | 3dm build | 3dm build | 3dm build |
| Info | 3dm info | 3dm info | 3dm 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 list | for x in a b c; do ... done | foreach ($x in @(...)) {...} | FOR %%X IN (a b c) DO ... |
| Make directory | mkdir -p dir | New-Item -Force -ItemType Directory dir | mkdir dir 2>nul |
| Copy file | cp src dst | Copy-Item src dst | copy src dst |
| Check exit code | if [ $? -ne 0 ] | if ($LASTEXITCODE -ne 0) | IF %ERRORLEVEL% NEQ 0 |
| Write to file | echo text > file | "text" | Out-File file | echo text > file |
| Append to file | echo text >> file | "text" | Add-Content file | echo text >> file |
| Date/time | date +%Y%m%d_%H%M%S | Get-Date -Format "yyyyMMdd_HHmmss" | wmic os get localdatetime |
| File size (bytes) | stat -c%s file | (Get-Item file).Length | FOR /F "tokens=4" %%S IN ('dir file') |
| Watch for changes | ls 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
| # | Title | Duration | Level | Main Topics | Key Project |
|---|---|---|---|---|---|
| 1 | Environmental Configuration | 60-90m | Beginner | Setup, project structure, 3dm build | None |
| 2 | Geometric Primitives & CSG | 60m | Beginner | Primitives, CSG operations, debugging | None |
| 3 | Parametric Architecture | 60m | Beginner+ | Modules, libraries, parameters | None |
| 4 | AI Verification | 45-60m | Intermediate | 3dm info, validation, design documentation | None |
| 5 | Safety & Physical Interface | 60-90m | Intermediate | Safety protocols, materials, pre-print checks | None |
| 6 | 3dm Commands & Text | 60-90m | Intermediate | 3dm info/preview/orient/slice, embossing | Keycap |
| 7 | Parametric Transforms | 75-90m | Intermediate+ | Transforms, multi-part design, assembly | Phone Stand |
| 8 | Advanced Parametric Design | 90-120m | Advanced | Tolerance, interlocking features, snap-fits | Stackable Bins |
| 9 | Automation & Workflows | 60-90m | Advanced | PowerShell scripting, batch processing, CI/CD | [key] Batch Automation |
| 10 | Troubleshooting & Mastery | 120-150m | Advanced | Measurement, QA testing, diagnostics | [dice] QA + Audit |
| 11 | Stakeholder-Centric Design | 90-120m | Advanced+ | Design thinking, user research, iteration | [beads] Jewelry Holder |
4 Reference Appendices
Quick links to comprehensive reference materials:
| Appendix | Focus | Size | Use When |
|---|---|---|---|
| A: Comprehensive Slicing Guide | PrusaSlicer, Bambu Studio, Cura, OrcaSlicer configuration | 1,500+ lines | Slicing questions, slicer reference |
| B: Material Properties & Selection Guide | Shrinkage data, print settings, material properties | 1,200+ lines | Choosing material, troubleshooting prints |
| C: Tolerance Testing & Quality Assurance Matrix | QA procedures, tolerance validation methods | 1,200+ lines | Quality verification, measurement techniques |
| D: PowerShell Integration for SCAD Workflows | Batch processing, automation scripts, workflow integration | 1,100+ lines | Building 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:
| Phone | Width | Angle | Result |
|---|---|---|---|
| iPhone | 60mm | 60 | Portrait viewing |
| iPad | 100mm | 40 | Landscape viewing |
| Tablet | 150mm | 35 | Document 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=12for faster test renders
Problem: Parts don’t fit together
Diagnosis:
- Print and test fit
- Measure with calipers
Solution:
- Adjust
stack_clear(smaller = tighter) - Increase
wallthickness - Test with tolerance matrix
Problem: Embossed text looks bad
Diagnosis:
- Check preview in slicer
- Use
3dm previewfor tactile version
Solution:
- Increase
letter_raise(deeper emboss) - Use larger
$fnintext() - 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
Resources & Links
Official Docs
Tutorials
Community
Tips & Tricks
Debugging
Tip
Lower
$fnto 8–12 during development for fast renders, then raise it to 32–64 for final export. High$fnvalues (especially with Minkowski) can make renders take minutes.
- Lower
$fnto 8-12 for faster renders during development - Use
3dm infofrequently to catch issues early - Test components individually before assembling
- Generate
3dm previewfor 2D tactile verification
Design
- Keep parameters at the top of file for easy modification
- Use descriptive names (not
w, usewidth) - 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 infoto verify non-visual usability and3dm previewto generate a tactile inspection image. Document all measurements clearly and test assembly without visual guidance.
- Always use
3dm infoto verify non-visual usability - Generate
3dm previewfor tactile inspection - Document measurements clearly
- Test assembly without visual guidance
Glossary
| Term | Definition |
|---|---|
| CSG | Constructive Solid Geometry - combining shapes using union/difference |
| Manifold | Water-tight geometry with clear inside/outside |
| Parametric | Driven by variables; changing parameters updates design |
| Tolerance | Acceptable variation in dimensions |
| Stack-up | Cumulative error from multiple tolerances |
| Module | Reusable code block in OpenSCAD |
| $fn | Resolution parameter (higher = more detail but slower) |
| G-code | Machine instructions for 3D printer |
| STL | 3D 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
-
Programming with OpenSCAD. https://programmingwithopenscad.github.io/ ↩
-
CadHub. OpenSCAD Review. https://learn.cadhub.xyz/blog/openscad-review/ ↩ ↩2
-
Deck, T. (2025). 3DMake. GitHub. https://github.com/tdeck/3dmake ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Class Central. OpenSCAD Courses. https://www.classcentral.com/subject/openscad ↩
-
ZenML. LLM-Powered 3D Model Generation. https://www.zenml.io/llmops-database/llm-powered-3d-model-generation-for-3d-printing ↩ ↩2 ↩3
-
Ohio State University EHS. https://ehs.osu.edu/kb/3d-printer-safety ↩ ↩2 ↩3 ↩4 ↩5
-
CDC/NIOSH. https://www.cdc.gov/niosh/blogs/2024/safe-3d-printing.html ↩
-
Washington State DoH. https://doh.wa.gov/community-and-environment/schools/3d-printers ↩ ↩2 ↩3
-
UTK EHS. https://ehs.utk.edu/index.php/table-of-policies-plans-procedures-guides/3d-printer-safety/ ↩
-
Gonzalez Avila et al. https://thomaspietrzak.com/bibliography/gonzalez24.pdf ↩
-
Reddit. https://www.reddit.com/r/openscad/comments/1fxj8xv/ ↩
-
OpenSCAD Issue #6297. https://github.com/openscad/openscad/issues/6297 ↩
-
Hacker News. https://news.ycombinator.com/item?id=46338565 ↩ ↩2
-
OpenSCAD Issue #6114. https://github.com/openscad/openscad/issues/6114 ↩
-
Tom’s Hardware. https://www.tomshardware.com/3d-printing/how-to-repair-stl-files-in-meshlab ↩
-
https://services.slcpl.org/creativelab ↩
-
https://www.slcolibrary.org/what-we-have/create ↩
-
https://www.weberpl.lib.ut.us/use-your-library/makerspaces ↩
-
https://library.washco.utah.gov/st-george/makerspace/ ↩
-
https://library.loganutah.org/about_us/services/makerspace.php ↩
-
https://www.lib.utah.edu/services/3d-printing.php ↩
-
3DMake GitHub Repository — Command reference including
3dm info. https://github.com/tdeck/3dmake ↩ -
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 Problem Sets: Advanced Problem Sets — Extended practice and challenge exercises for instructors and students.
- Command Line Appendices: Command Line Appendices — Reference material and in-depth command-line guides.
- 3D Make & OpenSCAD Appendices: 3D Make and OpenSCAD Appendices — Additional tutorials, patterns, and design references.
- Technical References & Troubleshooting: Technical References and Troubleshooting — Troubleshooting notes, technical tips, and reference tables.
- About the Author: About the Author — Contributor and author information.
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
| Appendix | Shell | Title |
|---|---|---|
| Appendix A | CMD / Batch | Command Line (CMD/Batch) Integration for SCAD Workflows |
| Appendix B | PowerShell | PowerShell Integration for SCAD Workflows |
| Appendix C | Git Bash / POSIX | Git 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
.bathelpers. - 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)
- Open SCAD manually -> Edit parameters -> Save -> Export STL
- Open Slicer manually -> Load STL -> Adjust settings -> Slice -> Export G-code
- Transfer G-code to printer via USB
- Record results in notebook
- Repeat for next variation (variant 2, variant 3, etc.)
Time: ~20-30 minutes per design iteration
Automated Workflow (Fast & Reproducible)
- Create PowerShell script with design parameters
- Script automatically:
- Generates SCAD code
- Exports to STL
- Slices to G-code
- Transfers to printer
- Logs results
- Run script once, walk away
- 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:
- Open bracelet_holder.scad
- Change peg_diameter = 5
- Save, export, slice, print
- Change peg_diameter = 6
- Save, export, slice, print
- Change peg_diameter = 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 Lesson | SCAD Application | Example |
|---|---|---|
| PS 1: Navigation | Working with project directories | Using cd to navigate src/ -> stl/ -> gcode/ |
| PS 2: File Manipulation | Copying, organizing SCAD files | Copy design files, organize variants by date |
| PS 3: Piping & Objects | Pass data between scripts | $results | Export-Csv exports analysis |
| PS 4: Variables & Aliases | Parameterize SCAD workflows | Variables store file paths, material types, etc. |
| PS 5: Functions & Modules | Reusable automation blocks | Build, slice, log = functions in one script |
| PS Unit Test | Verify workflow correctness | Test 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?
- Screen Reader Friendly: Console output = text (not UI clicks)
- Scriptable: Can run overnight, results logged
- Auditable: Every step written to log file
- Shareable: Scripts document the process for others
- 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
| Problem | Cause | Solution |
|---|---|---|
| Scripts won’t run | Execution policy | Set-ExecutionPolicy -ExecutionPolicy RemoteSigned |
| Command not found | Tool not in PATH | Specify full path: & "C:\Program Files\OpenSCAD\openscad.exe" |
| Files not created | Wrong working directory | Use absolute paths with Join-Path |
| Script hangs | Waiting for user input | Disable UI input; use -o flag for batch operations |
| CSV data corrupted | Special characters in notes | Properly quote strings in CSV export |
| No output/logging | Path doesn’t exist | Create directory first: New-Item -Type Directory -Path ... -Force |
Summary: PowerShell + SCAD Integration Benefits
Time Savings
| Task | Manual | Automated | Savings |
|---|---|---|---|
| Single design build | 5 min | 2.5 min | 50% |
| Test 10 parameter variations | 50 min | 5 min | 90% |
| Batch processing 20 designs | 100 min | 10 min | 90% |
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
- Try the basic build script (Script 1) with one of your SCAD files
- Add logging (Script 3) to track what you create
- Test parametric sweeps (Script 2) with design variations
- Integrate full workflow (Script 5) for complete automation
- 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.exewith 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 pipefailfor safer scripts. - Use
mktempor avariants/directory for generated files. - Keep heavy text processing to
pythonif 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
| Appendix | Title |
|---|---|
| Makerspace Index: Utah | Utah Makerspace Index (By County) |
| Makerspace Index: United States | National Makerspace Guide — State-by-State Index |
| Appendix A | 3DMake CLI Cheat Sheet |
| Appendix B | Comprehensive Slicing Guide — All Major Slicers |
| Appendix C | Material Properties and Selection Guide |
| Appendix D | Tolerance Testing and Quality Assurance Matrix |
| Appendix E | Advanced 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
Connecticut
- 2 makerspaces listed on GlobalSpec (e.g., CT Hackerspace).13
District of Columbia
Florida
Georgia
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
Kansas
- 14 statewide makerspaces.11
Kentucky
- 6 statewide makerspaces.11
Louisiana
- 3 statewide makerspaces.11
Maine
- 11 statewide makerspaces.11
Maryland
Massachusetts
Michigan
Minnesota
- 27 statewide makerspaces.11
Mississippi
- 3 statewide makerspaces.11
Missouri
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
North Carolina
- 28 statewide makerspaces.11
North Dakota
- (No verified listings in sources)
Ohio
Oklahoma
- 8 statewide makerspaces.11
Oregon
- 35 statewide makerspaces.11
Pennsylvania
- 15 statewide makerspaces.11
Rhode Island
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
Utah
- 9 statewide makerspaces.11
Vermont
- 6 statewide makerspaces.11
Virginia
Washington
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
3dmcommand-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
| Action | Description |
|---|---|
setup | Set up 3DMake for the first time, or overwrite/upgrade existing settings (printer profile, Gemini AI key, OctoPrint connection) |
new | Interactively 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:
| Action | Description |
|---|---|
build | Compile the OpenSCAD .scad source file into a .stl model |
orient | Auto-orient the model to minimize the need for supports (uses Tweaker3) |
slice | Slice the model into printer-ready G-code using PrusaSlicer |
print | Send 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,
slicewill implybuildif needed.
Inspection & Visualization
| Action | Description |
|---|---|
info | Display mesh dimensions and center point; optionally get an AI description of the model (requires Gemini or OpenRouter API key configured) |
preview | Produce a 2D silhouette projection of the model (outputs a flat STL for quick reference) |
image | Export 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 Name | Description |
|---|---|
3sil | Three-view silhouette (top, left, front) — default |
topsil | Top-down silhouette only |
leftsil | Left-side silhouette only |
rightsil | Right-side silhouette only |
frontsil | Front silhouette only |
backsil | Back silhouette only |
Available --colorscheme options for image:
| Scheme Name | Description |
|---|---|
slicer_light | Orange model on light gray background |
slicer_dark | Orange model on dark background |
light_on_dark | Floral 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):
| Action | Description |
|---|---|
edit-model | Open the current model’s .scad source file in your configured editor |
edit-profile | Open the current printer profile .ini file in your editor |
edit-overlay | Open (or create) a slicer settings overlay file in your editor |
edit-profile-gcode | Interactively select and edit a G-code script embedded in the printer profile |
edit-prompt | Edit the AI prompt used by the info command |
edit-global-config | Edit 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
| Action | Description |
|---|---|
list-libraries | List all available OpenSCAD libraries in the catalog, showing which are installed and their versions |
install-libraries | Download 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
| Action | Description |
|---|---|
list-profiles | List all available printer profiles |
list-overlays | List 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
| Action | Description |
|---|---|
test-connect | Test the connection to the configured print server (OctoPrint or Bambu LAN) |
help | Display the help message with all actions and options |
version | Print 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
| Option | Short | Type | Description |
|---|---|---|---|
--scale | -s | float or auto | Scale the model by a decimal factor (e.g. 1.5 for 150%, 0.5 for 50%) |
--model | -m | string | Select a specific model by name in a multi-model project (omit .scad extension) |
--profile | -p | string | Select a printer profile by name |
--overlay | -o | string | Apply a slicer settings overlay; can be used multiple times |
--view | -v | string | Select the preview view type (see view options above) |
--angle | -a | string | Set a viewpoint for image export; can be used multiple times |
--copies | -c | int | Number of copies to slice/print (default: 1) |
--interactive | -i | flag | Start an interactive AI chat after the info command |
--colorscheme | — | string | Color scheme name for image export |
--image-size | — | WxH | Image dimensions in pixels (e.g. 1920x1080, default: 1080x720) |
--debug | — | flag | Enable debug output (shows full subprocess logs, raises exceptions) |
--help / --h | -h | flag | Display 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
.scadfile,buildis 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-configto opendefaults.tomlin your editor.
Settings set via CLI flags (e.g.--scale,--profile) override both files at runtime.
General / Project Settings
| Key | Type | Default | Description |
|---|---|---|---|
model_name | string | "main" | The default model name. Maps to src/<name>.scad and build/<name>.stl |
project_name | string | (folder name) | Project name used as a prefix on output filenames. Auto-detected from directory name if not set |
scale | float | 1.0 | Scale factor applied during slicing. 1.0 = 100%, 1.5 = 150%, 0.5 = 50% |
copies | int | 1 | Number of copies to slice/print in one run |
strict_warnings | bool | false | Pass --hardwarnings to OpenSCAD — treat all warnings as errors during build |
min_3dmake_version | string | (none) | Minimum required 3DMake version to run this project. Prevents running with outdated installs |
interactive | bool | false | Default to interactive AI chat mode after info |
debug | bool | false | Enable 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
| Key | Type | Default | Description |
|---|---|---|---|
libraries | list 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_libraries | list 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
| Key | Type | Default | Description |
|---|---|---|---|
printer_profile | string | (required) | Name of the printer profile .ini file to use (without the .ini extension). Set during 3dm setup |
overlays | list of strings | [] | Default slicer setting overlays to apply on every slice. Profile-specific versions are preferred over default ones when available |
view | string | "3sil" | Default preview view type used by the preview action |
image_angles | list of strings | [] | Default viewpoint angles for the image action |
colorscheme | string | "slicer_light" | Default color scheme for the image action |
image_size | string | "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"
Print Sending Settings
| Key | Type | Default | Description |
|---|---|---|---|
print_mode | string | (required to print) | How to send prints to the printer. One of: "octoprint", "bambu_lan", "bambu_connect" |
auto_start_prints | bool | true | When 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.
| Key | Type | Default | Description |
|---|---|---|---|
octoprint_host | string | (none) | Full URL to your OctoPrint server, including protocol (e.g. "http://octopi.local" or "http://192.168.1.50") |
octoprint_key | string | (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.
| Key | Type | Default | Description |
|---|---|---|---|
bambu_host | string | (none) | Local IP address of your Bambu printer on your network (e.g. "192.168.1.42") |
bambu_serial_number | string | (none) | Printer serial number (found in the printer’s settings screen or Bambu Studio) |
bambu_access_code | string | (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.
| Key | Type | Default | Description |
|---|---|---|---|
gemini_key | string | (none) | Google Gemini API key for AI model descriptions. Free tier allows ~50 requests/day. Get one at aistudio.google.com/app/apikey |
openrouter_key | string | (none) | OpenRouter API key (alternative to Gemini for AI descriptions, supports many LLM providers) |
llm_name | string | (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
| Key | Type | Default | Description |
|---|---|---|---|
editor | string | (system default) | Command used to open files for editing (e.g. "code", "vim", "notepad", "subl"). Used by all edit-* actions |
edit_in_background | bool | false | Launch 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
| Variable | Description |
|---|---|
3DMAKE_CONFIG_DIR | Override 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
- When slicing, 3DMake loads your base printer profile first, then applies each overlay in order, with later overlays winning over earlier ones.
- Overlay files only need to contain the keys you want to change — all other profile settings are preserved.
- 3DMake looks for overlays in two places, preferring the printer-specific version if it exists:
overlays/<printer_profile>/<name>.ini← preferredoverlays/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
| Key | Description | Sample Values |
|---|---|---|
perimeters | Number of outer wall loops | 2 (draft) · 3 (normal) · 5 (strong) |
top_solid_layers | Solid layers on the top surface | 3 (draft) · 5 (normal) · 8 (strong) |
bottom_solid_layers | Solid layers on the bottom surface | 3 (draft) · 4 (normal) · 6 (strong) |
top_solid_min_thickness | Minimum top skin thickness in mm (overrides layer count if larger) | 0.5 · 0.8 · 1.0 |
bottom_solid_min_thickness | Minimum bottom skin thickness in mm | 0.5 · 0.8 · 1.0 |
external_perimeters_first | Print outer walls before inner walls (better surface quality) | 0 · 1 |
thin_walls | Detect and print thin walls that would otherwise be missed | 0 · 1 |
Infill
| Key | Description | Sample Values |
|---|---|---|
fill_density | Infill percentage | 5% · 15% · 20% · 40% · 60% |
fill_pattern | Infill pattern | grid · gyroid · honeycomb · cubic · rectilinear · lightning · triangles |
top_fill_pattern | Pattern for top solid layers | rectilinear · monotonic · concentric · smooth |
bottom_fill_pattern | Pattern for bottom solid layers | rectilinear · monotonic · concentric |
infill_every_layers | Only infill every N layers (speeds up print, reduces strength) | 1 · 2 · 3 |
solid_infill_every_layers | Force solid infill every N layers | 0 (off) · 5 |
infill_overlap | How much infill overlaps with perimeters (%) | 15% · 25% |
Layer Height & Speed
| Key | Description | Sample Values |
|---|---|---|
layer_height | Standard layer height in mm | 0.1 · 0.15 · 0.2 · 0.3 |
first_layer_height | Height of the first layer (absolute mm or %) | 0.2 · 0.25 · 75% |
perimeter_speed | Speed for perimeter walls (mm/s) | 40 · 60 · 80 |
external_perimeter_speed | Speed for outermost wall only (slower = better quality) | 25 · 35 · 50% |
infill_speed | Speed for infill (mm/s) | 60 · 80 · 120 |
solid_infill_speed | Speed for solid infill layers (mm/s) | 50 · 70 |
top_solid_infill_speed | Speed for top surface layers (slower = smoother) | 30 · 40 · 50 |
travel_speed | Non-extrusion travel speed (mm/s) | 130 · 180 · 250 |
first_layer_speed | First layer speed (mm/s or %) | 20 · 30 · 50% |
Supports
| Key | Description | Sample Values |
|---|---|---|
support_material | Enable support structures | 0 · 1 |
support_material_auto | Auto-detect where supports are needed | 0 · 1 |
support_material_threshold | Overhang angle above which supports are added (degrees) | 40 · 45 · 55 |
support_material_pattern | Support infill pattern | rectilinear · honeycomb · lightning |
support_material_spacing | Distance between support lines (mm) | 2 · 2.5 · 3 |
support_material_contact_distance | Z gap between support and part (mm) | 0.1 · 0.2 · 0.25 |
support_material_interface_layers | Dense interface layers between support and part | 0 · 2 · 3 |
Cooling & Bridging
| Key | Description | Sample Values |
|---|---|---|
cooling | Enable fan cooling | 0 · 1 |
min_fan_speed | Minimum fan speed % | 20 · 35 · 50 |
max_fan_speed | Maximum fan speed % | 50 · 80 · 100 |
bridge_fan_speed | Fan speed during bridges % | 80 · 100 |
bridge_speed | Extrusion speed for bridges (mm/s) | 20 · 30 · 40 |
bridge_flow_ratio | Flow rate multiplier for bridges | 0.8 · 0.9 · 1.0 |
Skirt, Brim & Raft
| Key | Description | Sample Values |
|---|---|---|
skirts | Number of skirt loops | 0 · 1 · 3 |
skirt_distance | Distance from part to skirt (mm) | 3 · 5 · 6 |
brim_width | Brim width in mm (0 = disabled) | 0 · 3 · 5 · 8 |
raft_layers | Number of raft layers (0 = disabled) | 0 · 2 · 3 |
Temperature
| Key | Description | Sample Values |
|---|---|---|
temperature | Hotend temperature for all layers (°C) | 200 · 215 · 230 |
first_layer_temperature | Hotend temperature for first layer only | 215 · 225 · 235 |
bed_temperature | Bed temperature for all layers (°C) | 0 · 55 · 60 · 80 |
first_layer_bed_temperature | Bed temperature for first layer only | 60 · 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.
| Action | Why it’s last |
|---|---|
image | Produces image files; nothing meaningful can follow a render |
info | Terminal inspection command; no build artifact is produced |
preview | Produces 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
Print / Connection Errors
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:
| Variable | Meaning | Recommended |
|---|---|---|
$fn | Fixed number of fragments | 32 for small circles, 64+ for large |
$fa | Minimum angle per fragment (degrees) | 1 for smooth curves |
$fs | Minimum 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=16or$fn=24during development for fast preview renders, then raise it to$fn=64or higher before your final3dm buildfor 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:
| Feature | Minimum |
|---|---|
| Wall thickness | 0.8mm (2× nozzle) — ideally 1.2mm+ |
| Hole diameter | 2mm (smaller holes tend to close up) |
| Gap / clearance between parts | 0.2–0.3mm for sliding fit, 0.1mm for press fit |
| Text / embossed detail | 0.5mm depth, 4pt font minimum |
| Pin diameter | 2mm 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)
| Parameter | What It Does | Typical Range | Impact |
|---|---|---|---|
| Nozzle Temp | Filament melting heat | 200-250C | Too cold -> weak; too hot -> oozing |
| Bed Temp | Build plate heat | 50-110C | Helps adhesion; prevents warping |
| Layer Height | Z-axis precision | 0.1-0.4mm | Finer = slower, better detail |
| Print Speed | Movement velocity | 30-150 mm/s | Faster = worse quality; slower = stronger |
| Infill % | Interior density | 10-100% | Higher = stronger + heavier |
| Support | Temporary scaffolding | On/Off | Required for overhangs >45 |
| Bed Adhesion | First layer stickiness | Brim/Raft/Skirt | Prevents 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:
| Setting | Location | Beginner Value | Why |
|---|---|---|---|
| Layer Height | Print Settings | 0.15mm | Balance speed & quality |
| Infill | Print Settings | 20% | Enough strength; fast print |
| Support | Print Settings | Yes (if needed) | For overhangs >45 |
| Nozzle Temp | Filament Settings | 210C | Default for PLA |
| Bed Temp | Filament Settings | 60C | Standard PLA adhesion |
| Print Speed | Print Settings | 150 mm/s | Balanced 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
| Problem | Cause | Solution |
|---|---|---|
| First layer not sticking | Bed not level | Bed leveling procedure in printer manual |
| Supports everywhere | No support type selected | Change to “Linear” or “Grid” |
| Nozzle drags through model | Z-offset too low | Raise Z-offset +0.1mm |
| Oozing strings between parts | Temp too high | Lower nozzle temp 5-10C |
| Print breaks mid-way | Adhesion problem | Add 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
- Launch Bambu Studio
- Sign in with Bambu Lab account
- Select printer from network
- Studio auto-detects printer settings
Step 2: Load Model & Configure
- Drag STL into workspace
- Auto-arranges on bed plate
- Default profile applied automatically
Step 3: Key Settings (Bambu-Specific)
| Setting | Default | Adjustment | Why |
|---|---|---|---|
| AMS Multi-Color | Off | On (if AMS attached) | Auto-switch filament |
| Auto-Leveling | Enabled | Keep On | Bambu feature-very reliable |
| Nozzle Temp | 220C | Keep unless specified | Bambu-optimized |
| Layer Height | 0.2mm | 0.15mm for detail | Balance speed/quality |
| Bed Temp | 65C | 60C for PLA | Standard adhesion |
Step 4: Send to Printer
- Click “Prepare” (bottom right)
- Review preview
- Click “Send to Device”
- Printer receives over WiFi
- 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
| Problem | Cause | Solution |
|---|---|---|
| WiFi not connecting | Network issue | Restart printer WiFi; check SSID |
| AMS not switching | Filament not detected | Load filament into AMS; recalibrate |
| Print quality inconsistent | Wrong filament type | Run filament calibration |
| Nozzle crashes on first layer | Auto-level failed | Manually 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
- Launch Cura
- Go to “Settings” (top-right)
- Click “Printers” -> “Add Printer”
- Select your printer model from list
- Confirm network connection
Step 2: Load & Prepare Model
- Drag STL into workspace
- Model auto-scales if needed (confirm size)
- Right-click -> “Support” (if overhangs need support)
Step 3: Recommended Settings
| Setting | Value | Notes |
|---|---|---|
| Profile | Standard | Good balance for most prints |
| Layer Height | 0.2mm | Default; change to 0.15mm for detail |
| Infill | 20% | 100% waste for solid parts |
| Support Angle | 50 | Auto-generates support for overhangs |
| Build Plate Adhesion | Brim | Helps first layer stick |
| Nozzle Temp | 200C | Standard PLA |
| Bed Temp | 60C | Standard PLA |
Step 4: Print
- Click “Slice” (bottom right)
- Review layer-by-layer preview
- Click “Print Over Network” or “Print to File”
- 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
| Problem | Cause | Solution |
|---|---|---|
| Model appears too small on bed | Scale wrong | Right-click -> Scale to fit |
| Stringing between parts | Retraction disabled | Enable retraction in settings |
| Support doesn’t generate | Auto-support off | Enable “Generate Support” |
| Printer not found | Network/USB issue | Check 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
| Feature | PrusaSlicer | SuperSlicer |
|---|---|---|
| Arachne Engine | No | Yes-better edges |
| Seam Position | Limited options | Full control |
| Pressure Equalization | No | Yes-better bridging |
| Stealth Mode | No | Yes-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
- Download SuperSlicer from GitHub
- Export profile from PrusaSlicer (if you have it)
- Import into SuperSlicer
- 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
- Download OrcaSlicer
- Select your printer (not just Bambu models)
- Load STL
- Uses good defaults-usually ready to print
Key Settings
| Setting | Value | Why |
|---|---|---|
| Wall Loops | 2 | Strong walls, visible detail |
| Internal Solid Layer | 4 | Strength for brackets/connectors |
| Infill Pattern | Grid | Balanced strength |
| Line Width | Auto | Matches nozzle diameter |
| Speed | 80 mm/s | Balanced 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
- Launch IdeaMaker
- Add printer (Raise3D models have built-in profiles)
- Load STL
- Adjust layer height and infill
- 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
- Design in Fusion 360 (or import STL)
- Select part
- Go to “3D Print” tab
- Click “Print Preparation”
- View auto-generated support and alignment
- Adjust layer height, infill, etc.
- Slice and export G-code
Integration with 3dMake
If using Fusion 360 for CAD:
- Export SCAD design to STL
- 3dm export-stl src/main.scad output/main.stl
- Then import into Fusion 360
- For more complex designs that need refinement
Universal Troubleshooting Guide
| Problem | Diagnosis | Solution |
|---|---|---|
| Print won’t stick to bed | Bed temperature too low | Raise bed temp +5C; check bed level |
| Bed not level | Manual leveling procedure (printer manual) | |
| Build plate dirty | Clean with isopropyl alcohol | |
| Nozzle hits model mid-print | Z-offset wrong | Adjust Z-offset; re-level bed |
| Model placed too low on bed | Use “Arrange on Bed” tool in slicer | |
| Supports won’t remove | Too much support generated | Reduce support density or angle |
| Support too strong | Reduce support material percentage | |
| Stringy/Oozing | Nozzle too hot | Reduce temp by 5-10C |
| Retraction disabled | Enable retraction in settings | |
| Travel speed too fast | Reduce travel speed | |
| Layer shifting (X/Y) | Belt tension off | Check belt tension (printer manual) |
| Stepper motor power issue | Firmware issue-check printer logs | |
| Model prints poorly but slices look good | Filament quality issue | Try different filament batch |
| Nozzle clogged | Unclog nozzle (heat -> purge -> clean) |
Recommended Slicer for Each Situation
| Scenario | Best Slicer | Why |
|---|---|---|
| I’m a beginner | PrusaSlicer | Clear defaults, excellent UI |
| I have a Bambu printer | Bambu Studio | Native, best features |
| I have an Ultimaker | Cura | Official support, broad compatibility |
| I have a Raise3D | IdeaMaker | Official, dual-extrusion support |
| I want advanced control | SuperSlicer | Maximum customization |
| I want modern/fast slicing | OrcaSlicer | Great defaults, any printer |
| I use Fusion 360 for CAD | Fusion 360 Print Prep | Integrated 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
-
Weight Check:
- Calculate expected weight from volume + material density
- Compare to actual printed weight
- Indicates if infill is correct
-
Dimensional Check:
- Use calipers to verify critical dimensions
- Compare to SCAD parameters
- Check tolerance stack-up
-
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
| Property | Rating | Notes |
|---|---|---|
| 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
| Parameter | Value | Tolerance |
|---|---|---|
| Nozzle Temp | 200C | 190-210C (varies by brand) |
| Bed Temp | 60C | 50-65C |
| Print Speed | 50 mm/s | 40-60 mm/s |
| Retraction | 5mm @ 40 mm/s | Yes, prevents stringing |
| Cooling Fan | 100% | High cooling improves quality |
| First Layer | Slower (25 mm/s) | Ensures adhesion |
| Layer Height | 0.2mm | 0.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
| Problem | Cause | Solution |
|---|---|---|
| Warping on corners | Bed too hot or cooling too fast | Reduce bed temp to 50C; disable cooling for first layer |
| Stringing | Temp too high | Lower nozzle temp 5C |
| Poor layer adhesion | Nozzle too high | Lower Z-offset 0.1mm |
| Brittleness after print | Normal for PLA | Not a problem; expected behavior |
| Nozzle clogs on retraction | Temperature inconsistency | Ensure stable nozzle temp +/- 5C |
Why PLA for This Course
PLA is recommended for all Lessons 1-11 because:
- Beginner-friendly: Most forgiving material
- Predictable: Consistent across different printers
- Cost-effective: Maximize printing volume on student budget
- Accessibility: Easier to troubleshoot for new users
- Safe: Non-toxic, low fume emission
- Available: Found at any 3D printing supplier
2. PETG (Polyethylene Terephthalate Glycol)
Properties at a Glance
| Property | Rating | Notes |
|---|---|---|
| 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
| Parameter | Value | Tolerance |
|---|---|---|
| Nozzle Temp | 235C | 230-245C |
| Bed Temp | 80C | 75-85C |
| Print Speed | 50 mm/s | 40-60 mm/s (same as PLA) |
| Retraction | 4mm @ 40 mm/s | Slightly less than PLA |
| Cooling Fan | 30-50% | Less cooling than PLA |
| First Layer | Normal (50 mm/s) | Harder to adjust than PLA |
| Layer Height | 0.2mm | 0.1-0.3mm |
Comparison: PETG vs. PLA
| Aspect | PLA | PETG |
|---|---|---|
| Nozzle Temp | 200C | 235C |
| Bed Temp | 60C | 80C |
| Strength | Good | Better (20% stronger) |
| Flexibility | Brittle | More resilient |
| Heat Tolerance | 60C | 85C |
| Ease | Very easy | Easy (needs tweaking) |
| Cost | $20/kg | $25/kg |
| Outdoor Use | Not ideal | Better |
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
| Property | Rating | Notes |
|---|---|---|
| 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:
- Enclosed environment: Minimize temperature fluctuations
- Heated bed: 100C+ (much higher than PLA)
- Controlled cooling: Too-fast cooling causes warping
- Ventilation: ABS emits fumes (acetone-like smell)
Printing Parameters
| Parameter | Value | Tolerance |
|---|---|---|
| Nozzle Temp | 240C | 230-250C |
| Bed Temp | 100C | 95-105C |
| Enclosure | Required | Maintains heat (reduces warping) |
| Print Speed | 40 mm/s | Slower than PLA |
| Retraction | 3mm @ 30 mm/s | Very short |
| Cooling Fan | 0% | OFF (causes warping) |
| First Layer | Slow (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:
- Requires enclosed printer (expensive for beginners)
- High failure rate for inexperienced users
- Strong odor (ventilation concerns for some users)
- Requires extra equipment (acetone for post-processing)
4. TPU / TPE (Thermoplastic Polyurethane / Elastomer)
Properties at a Glance
| Property | Rating | Notes |
|---|---|---|
| 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
| Parameter | Value | Tolerance |
|---|---|---|
| Nozzle Temp | 215C | 210-225C |
| Bed Temp | 60C | 50-70C |
| Print Speed | 20-30 mm/s | VERY SLOW (flexibility needs time) |
| Retraction | Minimal or Off | 0-1mm (flexible material doesn’t retract well) |
| Cooling Fan | 0% | Off (material needs heat) |
| Line Width | 0.5mm | Wider 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
- Very slow printing: 5-10x slower than PLA
- Stringing: Flexible material tends to ooze
- Flexible bed needed: Standard beds may not work
- 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
| Property | Rating | Notes |
|---|---|---|
| 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
- Extreme difficulty (high failure rate)
- Very expensive (3-5x cost of PLA)
- Requires industrial-grade printer
- Post-processing complex
6. Nylon (PA)
Properties at a Glance
| Property | Rating | Notes |
|---|---|---|
| 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
| Material | Nozzle | Bed | Strength | Flexibility | Heat | Ease | Cost | Best For |
|---|---|---|---|---|---|---|---|---|
| PLA | 200C | 60C | [3/5] | [1/5] | [2/5] | [5/5] | $ | Beginners, detail |
| PETG | 235C | 80C | [4/5] | [2/5] | [3/5] | [4/5] | $$ | Functional parts |
| ABS | 240C | 100C | [4/5] | [3/5] | [5/5] | [2/5] | $$ | High-temp/mechanical |
| TPU | 215C | 60C | [3/5] | [5/5] | [3/5] | [3/5] | $$$ | Flexibility/tactile |
| PC | 280C | 110C | [5/5] | [2/5] | [5/5] | [1/5] | $$$$ | Extreme strength |
| Nylon | 250C | 85C | [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)
-
Weight Check
Known: 1kg spool Weigh spool + filament Calculate remaining filament Should match spool markings -
Diameter Check
Use caliper to measure multiple points Should be consistent +/- 0.03mm If varying, likely lower quality -
Dryness Test
Feel texture: Should be smooth, not tacky Smell: Should be neutral (not musty) If wet, store in sealed container with desiccant -
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
| Sign | Cause | Solution |
|---|---|---|
| Weak prints / breaking easily | Filament aged or wet | Replace with fresh filament |
| Discoloration or spots | Oxidation or contamination | Not usable; discard safely |
| Brittle or crumbly | Overheated or UV damage | Not usable; discard |
| Slight fading (color) | UV exposure | Still 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
- Buy bulk: 5kg spool is cheaper per gram than 1kg
- Buy sales: 30-40% discounts common during sales
- Brand matters: Premium brands slightly more but more reliable
- Generic brands: Often acceptable if reviews are good
Recommended Brands (Ranked by Beginner-Friendliness)
| Rank | Brand | Known For | Cost | Notes |
|---|---|---|---|---|
| 1 | Prusament | Reliability, Prusa compatibility | $$$ | Best; excellent support |
| 2 | MatterHackers | Quality, variety | $$ | Very good; educational focus |
| 3 | Fillamentum | European quality | $$ | Excellent; eco-friendly |
| 4 | Overture | Value, consistency | $ | Good budget option |
| 5 | eSUN | Variety, 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:
- Start with PLA: Best for learning; most forgiving
- Understand the tradeoffs: Strength vs. ease, cost vs. quality
- Match material to project: Decorative = PLA; functional = PETG
- Store properly: Desiccant, cool, dark location
- Track usage: Know what works for future projects
- 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
- Assembly: Parts must fit together
- Function: Fit too tight = stuck; too loose = falls apart
- Safety: Wrong tolerance = part failure
- 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:
- Gently close calipers until they barely touch the part
- Feel the resistance (should be light, not forced)
- Read digital display with audio feedback or manually
- Record three measurements at different locations
- 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:
- Place part on scale
- Wait for reading to stabilize (1-2 seconds)
- Read digital display (in grams)
- 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:
| Part | Dimension | Spec | Tolerance | How to Test |
|---|---|---|---|---|
| Bracelet Holder | Base width | 127mm | +/-2mm | Measure with calipers (multiple points) |
| Peg diameter | 6mm | +/-0.5mm | Test fit with go/no-go gauge | |
| Peg spacing | 8mm | +/-1mm | Measure distance between pegs | |
| Back wall height | 120mm | +/-2mm | Measure with calipers | |
| Phone Stand | Slope angle | 20 | +/-3 | Calculate from height/depth ratio |
| Weight capacity | 200g | 150-250g | Load test (see below) | |
| Stability | N/A | Pass/fail | 1-hour load test without tipping |
Pre-Print Planning
Before slicing, define:
- Critical dimensions: Which measurements matter most?
- Acceptable range: What tolerance is realistic?
- Test method: How will you verify?
- 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:
- Place part on flat surface
- Position caliper jaws perpendicular to surface
- Gently close jaws until they just touch part
- Feel for light resistance (not forced)
- Read digital display
- Record measurement
- Repeat at 3 different locations
- Average the three readings
- 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
- Insert caliper jaws into hole/around peg
- Adjust jaws to gently touch surfaces
- Feel for light resistance on both sides
- Read digital display (inside measurement mode)
- Record three measurements
- Average the readings
Method B: Go/No-Go Gauge
- Print test jigs (go & no-go gauges)
- Attempt to insert peg/hole into go-gauge -> Should slide through easily with light resistance
- Attempt to insert peg/hole into no-go-gauge -> Should NOT fit or fit with visible resistance
- 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
- Place part on digital scale
- Wait for reading to stabilize (1-2 seconds)
- Read display in grams
- Compare to expected weight
Step 3: Interpret Result
| Actual Weight | Interpretation |
|---|---|
| 290-315g | [YES] Correct infill, no internal voids |
| <280g | Infill too low or significant voids |
| >320g | Infill 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:
- Measure baseline dimensions (part unloaded) Baseline height: 60mm
- Place test weight on part Added weight: 200g
- Wait 5 minutes (allow part to settle)
- Measure dimensions again New height: 59.8mm Deflection: 0.2mm (acceptable)
- Observe for cracks (visual or tactile) No cracks: [YES]
- Remove weight and wait 5 minutes
- 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:
- Measure Part A opening: 50.1mm [YES]
- Measure Part B base: 49.8mm [YES]
- Attempt to nest Part B into Part A -> Should fit with light resistance -> Feel for smooth insertion (no catching)
- Check for rocking (part should sit stable)
- 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
- Record baseline dimensions
- Cycle 1: Place phone, tilt to max angle, remove
- Inspect for cracks or damage
- Repeat cycle 10 times
- Measure dimensions again
- 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
| Problem | Typical Cause | How to Fix | Prevent Next Time |
|---|---|---|---|
| Part too small (all dimensions off) | Scale wrong in slicer | Scale STL up in CAD or slicer | Verify scale before slicing |
| Holes too small | Compensation shrinkage | Increase hole diameter +0.5mm | Add shrinkage factor to design |
| Walls too thin | Layer squishing | Check first layer height; may need recalibration | Measure first layer thickness |
| Infill showing through (loose fill) | Infill too low | Increase infill % to 25-30% | Recalculate for part type |
| Inconsistent across print | Nozzle clogging mid-print | Clean nozzle; check filament quality | Use quality filament; monitor print |
| Z-axis dimensions off | Z-axis uncalibrated | Run Z-calibration procedure | Calibrate before critical prints |
| Dimensions change between prints | Thermal drift | Print in stable temperature | Use 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:
- Caliper measurements: Objective, quantifiable
- Weight verification: Numerical result
- Functional testing: Pass/fail criteria
- Go/No-Go gauges: Tactile pass/fail
- 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:
- Plan before printing: Define tolerances and test methods
- Measure precisely: Use calibrated tools (digital calipers, scale)
- Test functionally: Will parts assemble and work?
- Document quantitatively: Use numbers, not adjectives
- Iterate based on data: If test fails, adjust design or process
When to Use Each Test:
| Situation | Recommended Test |
|---|---|
| Prototype/mockup | Linear dimensions only |
| Assembly with other parts | Tolerance stack-up analysis |
| Load-bearing part | Functional load test |
| Repeated-use item | Durability cycling test |
| Multi-part design | Assembly 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
| Technique | Use Case | Complexity | Performance |
|---|---|---|---|
| Gears | Mechanical power transmission | High | Medium |
| Batch Processing | Design space exploration | Medium | Depends on scope |
| Performance Optimization | Reducing render time | Medium | High payoff |
| Orientation Analysis | Strength optimization | Medium | Simulation cost |
| Recursion | Fractal/nested structures | High | Can be expensive |
References and Further Learning
- OpenSCAD Documentation - Advanced Features: https://en.wikibooks.org/wiki/OpenSCAD_User_Manual
- Gear Design Theory: https://www.mekanizmalar.com/
- 3D Print Orientation Optimization: https://stratasys.com/
- Fractal Geometry: https://en.wikipedia.org/wiki/Fractal
- Recursive Algorithms: https://www.khanacademy.org/computing/computer-science/algorithms
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
-
Logan Library Cytiva STEM Makerspace. ↩
-
Utah STEM Action Center – Innovation Hub Network. ↩ ↩2 ↩3 ↩4
-
Salt Lake City Public Library Creative Lab. ↩
-
Salt Lake County Library Create Spaces. ↩
-
University of Utah – Marriott Library ProtoSpace & 3D Printing. ↩
-
Washington County Library – Sid Atkin Makerspace. ↩
-
Weber County Library Makerspaces. ↩
-
https://www.nationofmakers.us/find-a-maker-organization ↩
-
https://makerspacedir.com/ ↩
-
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
-
https://www.globalspec.com/local/6383/C_US ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
https://www.makerdirectory.com/makerspace-directory/ ↩
-
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
| Section | Title | Purpose |
|---|---|---|
| Technical Reference and Troubleshooting | Systems architecture, CLI reference, and fault-by-fault troubleshooting compendium | Diagnose and resolve errors in OpenSCAD, 3dMake, CMD, PowerShell, Git Bash, slicers, and printers |
| Student Glossary | Terms, definitions, and code examples across all curriculum systems | Look up any term encountered in lessons, with syntax examples for each shell |
| Teacher Glossary | Pedagogical frameworks, instructional strategies, and assessment rubrics | Instructors: curriculum design, scaffolding, computational thinking, and cross-curricular connections |
| Further Reading and References | Scholarly works, official documentation, industry resources, and community links | Continue 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 shapesminkowski()— Slow but precise
Use hull() when possible.
H. SYSTEM DIAGNOSTIC CHECKLIST
- Is OpenSCAD in PATH?
- Does CLI produce STL?
- Is STL manifold?
- Does slicer preview correctly?
- Is G-code generated?
- Does printer firmware accept G-code?
- Is first layer adhering?
- Are dimensions within tolerance?
- Are all brackets matched?
- Are comments properly closed?
- Is $fn set reasonably?
- Are transform operations in correct order?
J. EDITOR AND IDE TROUBLESHOOTING
J.1 VS Code OpenSCAD Extension Issues
Symptom:
- No syntax highlighting
Fix:
- Install “OpenSCAD” extension
- Restart VS Code
- Check file extension is
.scad
J.2 Notepad++ Syntax Highlighting
Setup:
- Settings > Style Configurator
- Select Language: C or C++
- Apply to
.scadfiles
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:
- Write permissions
- Sufficient disk space
- 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.
Print Working Directory
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:
- Base plate
- Support angle
- Lip to hold phone
- 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
- Create basic cube
- Add one parameter
- Add one transformation
- Build and verify
- 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:
- Interview stakeholders
- Define requirements
- Create design constraints
- Iterate based on feedback
Example: Design assistive device for specific user needs.
SECTION III — Assessment & Validation
Code Review Criteria
Assess student code on:
- Functionality — Does it work?
- Parametrization — Are values abstracted?
- Documentation — Are comments clear?
- Modularity — Is code reusable?
- 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
- Semantic HTML/Markdown — Proper heading structure
- Alt text for images — Describe geometric concepts
- CLI-first workflows — Reduce GUI dependence
- Descriptive output —
3dm infoprovides text descriptions
Braille Display Setup
For students using refreshable braille displays:
- Ensure code editors support screen readers
- Use semantic indentation (not tabs)
- Provide geometric descriptions in text
- 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:
- CLI navigation (
pwd,ls,cd) - Text editor setup (VS Code with extensions)
3dm buildcommand3dm infofor validation- 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
- Cube
- Sphere
- Cylinder (including cones)
- Boolean operations
- Transformations
- Compound models
Tolerance Management
Critical mechanical engineering concept.
Teaching Approach
- Print test parts
- Measure with calipers
- Calculate error
- Adjust tolerance parameters
- 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:
.scad— Source code.stl— 3D mesh.gcode— Machine instructions
Each represents different abstraction level.
Debugging Strategies
Systematic approaches to finding errors.
For Students
- Read error messages carefully
- Use
echo()to print values - Test modules independently
- Use
#modifier to highlight geometry - 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:
- Define problem
- Research requirements
- Brainstorm solutions
- Build prototype
- Test and evaluate
- 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:
- Explain why, not what
- Document parameters
- Include units
- Note constraints
Arithmetic in Code
Reinforce math concepts:
width = 10;
spacing = width * 1.5; // Arithmetic
SECTION X — Assessment Rubrics
Parametric Design Rubric
| Criterion | Novice | Developing | Proficient | Advanced |
|---|---|---|---|---|
| Parameterization | Hard-coded values | Some parameters | Most values parameterized | Full parametric architecture |
| Documentation | No comments | Minimal comments | Clear parameter docs | Comprehensive documentation |
| Modularity | No modules | Basic modules | Reusable modules | Library-quality modules |
| Functionality | Doesn’t build | Builds with errors | Meets requirements | Exceeds requirements |
Manufacturing Readiness Rubric
| Criterion | Assessment |
|---|---|
| Manifold geometry | Pass/Fail |
| Tolerance specified | Pass/Fail |
| Documentation complete | Pass/Fail |
| Quality measurements recorded | Pass/Fail |
SECTION XI — Troubleshooting Pedagogy
Teaching Debugging
Framework:
- Reproduce — Can you make it fail consistently?
- Isolate — What’s the minimal failing case?
- Hypothesize — What might cause this?
- Test — How can you verify?
- 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
- Week 1-2: Primitives and transformations
- Week 3-4: Modules and parameters
- Week 5-6: Boolean operations
- Week 7-8: Multi-part assemblies
- 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.