---
title: Tutorial 40 Feedback Loops (Closed Loop Printing)
description: Making the printer smart enough to fix itself.
---
Tutorial 40 Feedback Loops (Closed Loop Printing)
1. Lesson Header
- Lesson Number: 40
- Level: Master
- Title: Feedback Loops (Closed Loop Printing)
- Estimated Duration: 60 Minutes
- Prerequisites: Lesson 39 (Streaming), Lesson 26 (Conditionals)
- What You Will Build: A "Self-Correcting" Print Script.
2. Concept Introduction
Open Loop vs Closed Loop.
Standard G-code is Open Loop: "Move X100" -> The printer assumes it moved 100mm.
If it hits a clamp or skips a step, it doesn't know.
Closed Loop adds sensors: "Move X100" -> Encoder says "Moved 99mm" -> "Move X1 more".
3. Machine State Explanation
The Feedback Signal.
- Encoders: Measure motor rotation.
- Filament Sensor: Measures diameter/movement.
- Probe (BLTouch): Measures Z height.
- Camera: Measures print failure (Spaghetti Detective).
4. Command Breakdown
- M114: Get Current Position.
- M119: Get Endstop Status.
- M600: Filament Change (triggered by sensor).
5. Minimal Working Example
The Dynamic Z-Offset.
Probe the bed at (X, Y).
If Z < 0 (Bed is high), adjust G92 Z... or use M290 (Babystep).
6. Visual Representation
Interactive preview is available in the interactive reader.
7. Build Exercise
Task: Simulate a "Filament Width Compensator".
Imagine you have a sensor that reads filament diameter (1.75mm +/- 0.05).
Write a Python script that streams G-code but adjusts the E value based on a mock sensor reading.Volume = Area * Length.Area = PI * (Diameter/2)^2.
If Diameter drops to 1.70, Area decreases, so Length (E) must increase to maintain Volume.
Formula:Factor = (1.75 / Measured_Diameter)^2.New_E = Original_E * Factor.
8. Deep Insight Section
PID Tuning.
Temperature control (M301) is the most common closed loop.Error = Target - Current.Output = P*Error + I*Sum(Error) + D*Delta(Error).
You can implement PID for anything!
Example: Chamber Heater Control using a fan and a spare thermistor.
9. Common Failure Modes
- Oscillation: If your feedback loop is too aggressive (High P-term), the printer will shake violently trying to correct tiny errors.
- Sensor Noise: If your filament sensor reads "1.75, 1.60, 1.75" due to noise, your extruder will stutter. You need a Moving Average Filter.
10. Real-World Application
Non-Planar Ironing with Load Cells.
Some high-end machines measure the force on the nozzle.
If the force is too high (scratching), they lift Z.
If too low (air gap), they lower Z.
This allows perfect ironing on uneven surfaces.
11. Final Clean Version
The Compensator Script:
import random
nominal_d = 1.75
current_e = 0
def read_sensor():
# Simulate noisy sensor
return nominal_d + random.uniform(-0.05, 0.05)
def process_gcode_line(line):
global current_e
if "E" in line:
# Parse E value
parts = line.split()
new_parts = []
for p in parts:
if p.startswith("E"):
val = float(p[1:])
# Calculate compensation
d = read_sensor()
factor = (nominal_d / d) ** 2
# Assume relative E for simplicity
compensated_e = val * factor
new_parts.append(f"E{compensated_e:.5f}")
print(f"Compensating: D={d:.2f}mm -> Factor={factor:.2f}")
else:
new_parts.append(p)
return " ".join(new_parts)
return line
# Test
gcode = ["G1 X10 E1", "G1 X20 E1", "G1 X30 E1"]
for l in gcode:
print(process_gcode_line(l))
12. Stretch Challenge
Challenge: Implement Spaghetti Detection.
Write a script that takes a camera image (mock function get_image_darkness()).
If the image is too dark (print detached and covering lens?) or too static (not moving?), trigger M600 (Pause).
Hint: This usually requires Computer Vision (OpenCV), but you can simulate the logic.