Compare commits

...

5 commits

Author SHA1 Message Date
01113d31e5 clean up 2026-03-18 22:05:03 -07:00
85ee00dc19 Fixed labels which previously went off edges of bar and tower. 2026-03-18 22:04:17 -07:00
John Poole
d9e3b5520f README.md generated from ChatGPT, such as it is 2026-03-18 22:02:20 -07:00
John Poole
da500146f5 All printed successfully 2026-03-18 20:34:42 -07:00
1229644aa6 created models 2026-03-17 14:16:18 -07:00
22 changed files with 635810 additions and 2 deletions

260
README.md
View file

@ -1,3 +1,259 @@
# motion-diagnostics-suite
# sv06-belt-recovery-stress-tests
Parametric OpenSCAD models and procedures for diagnosing layer shifts, belt tension, and motion instability in FDM 3D printers.
Belt tension recovery and motion stability test models for bed-slinger 3D printers (e.g., SV06-class machines).
---
![](img/DSC_5098.webp)
## Purpose
These models are designed to help recover from situations where printer motion accuracy has been degraded, typically due to:
* Adjusting belt tension without a reference baseline
* Experiencing layer shifts during prints
* Replacing belts or modifying mechanical components
This project provides:
* Parametric OpenSCAD models
* A structured test procedure
* Guidance for interpreting failure modes
---
## When To Use This
Use these tests if you observe:
* Sudden layer shifts (e.g., 3-5 mm offsets)
* Inconsistent dimensional accuracy
* Audible belt skipping or motor stutter
* After adjusting belt tensioners
Here's an example of a case for a hand held radio where the top suddendly shift at the 20mm height.
![](img/20260318_215156_Wed.png)
---
## Models Included
### 1. Cube (Baseline Test)
* Dimensions: 40 × 40 × 40 mm
* Purpose:
* Verify basic printer stability
* Detect gross mechanical issues
---
### 2. Y-Bar (Axis Stress Test)
* Dimensions: 20 × 150 × 50 mm
* Purpose:
* Stress the Y-axis (bed movement)
* Detect belt slip under momentum and direction reversal
**Important:**
* Orient the 150 mm dimension front-to-back on the bed
---
### 3. Tower (Long-Duration Test)
* Dimensions: 18 × 18 × 120 mm
* Purpose:
* Reveal issues that appear only over time
* Detect cumulative drift, resonance, or late-stage layer shifts
---
## Print Procedure (Recommended Order)
Run each model as a **separate print job**:
1. **Cube**
* Confirms system is not fundamentally broken
2. **Y-Bar**
* Directly tests axis tension and inertia behavior
3. **Tower**
* Tests stability over time and height
---
## Suggested Slicer Settings (Orca Slicer)
### Cube
* Layer height: 0.20 mm
* Perimeters: 3
* Infill: 20-25% (grid or gyroid)
### Y-Bar
* Layer height: 0.20 mm
* Perimeters: 3
* Infill: 15-25% (grid recommended)
### Tower
* Layer height: 0.20 mm
* Perimeters: 3
* Infill: 0-10%
* Brim: optional (only if adhesion is an issue)
See the settings folder for settings used in Orca Slicer.
---
## Belt Tension Guidance
This project assumes GT2 belts (typical for most hobby printers).
### Frequency Method (Recommended)
Using a phone-based spectrum analyzer:
* Target range: **90-110 Hz**
* Reference: ~110 Hz ? ~2 lb tension (Voron baseline)
Procedure:
1. Move bed so belt span ~ 150 mm
2. Pluck belt
3. Measure frequency
4. Adjust tensioner
5. Repeat until stable
### Notes
* Too loose:
* Low frequency (<70 Hz)
* Layer shifts likely
* Too tight:
* High frequency (>120-130 Hz)
* Motor strain, possible missed steps
---
## Interpreting Results
### Good Result
* Clean vertical alignment
* No sudden offsets
* Consistent layer stacking
---
### Failure Modes
#### Sudden Layer Shift
* Cause:
* Belt too loose
* Pulley slipping
* Action:
* Increase tension slightly
* Check motor pulley set screws
---
#### Repeated Shift at Same Height
* Cause:
* Mechanical obstruction
* Cable snag
* Action:
* Inspect motion path
* Check wiring harness clearance
---
#### Gradual Lean / Drift
* Cause:
* Frame or axis alignment issue
* Action:
* Inspect rails, wheels, or rods
---
#### Ringing / Ghosting (No Shift)
* Cause:
* High acceleration
* Action:
* Reduce acceleration (not a belt issue)
---
## Notes on Methodology
These tests intentionally:
* Emphasize repeated motion in one axis
* Increase inertial load with height
* Create conditions where marginal tension fails visibly
This approach isolates motion system issues rather than general print quality.
---
## OpenSCAD Usage
Generate models:
```bash
openscad -D 'model="cube"' -o cube_$(date +%Y%m%d_%H%M).stl stress_test_models.scad
openscad -D 'model="ybar"' -o ybar_$(date +%Y%m%d_%H%M).stl stress_test_models.scad
openscad -D 'model="tower"' -o tower_$(date +%Y%m%d_%H%M).stl stress_test_models.scad
```
---
## Provenance
Generated with:
* OpenSCAD
* Orca Slicer (recommended)
* Frequency-based belt tuning derived from:
* Voron Design tuning methodology
This project was developed with ChatGPT.
---
## License
Recommend: MIT or CC-BY 4.0 for broad reuse.
---
## Contributing
Improvements welcome:
* Additional test geometries
* Axis-specific stress models
* Automated calibration workflows
---

BIN
img/20260318_215156_Wed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
img/DSC_5098.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

View file

@ -0,0 +1,205 @@
//
// stress_test_models.scad
// 20260317 ChatGPT
// $Id$
// $HeadURL$
//
// Example command lines:
//
// openscad -D 'model="cube"' -o cube_20260317_1335.stl stress_test_models.scad
// openscad -D 'model="ybar"' -o ybar_20260317_1335.stl stress_test_models.scad
// openscad -D 'model="tower"' -o tower_20260317_1335.stl stress_test_models.scad
// openscad -D 'model="all"' -o all_20260317_1335.stl stress_test_models.scad
//
// Suggested slicer use:
//
// 1) Print each model as a SEPARATE run.
// 2) For ybar, orient the LONG dimension along the printer's Y axis
// so the bed moves the long way front-to-back.
// 3) Infill is set in Orca Slicer, not here.
//
// Suggested slicer settings:
//
// cube: 0.20 layer, 3 perimeters, 20-25% grid or gyroid
// ybar: 0.20 layer, 3 perimeters, 15-25% grid
// tower: 0.20 layer, 3 perimeters, 0-10% infill, no brim at first;
// add brim only if adhesion becomes the issue rather than motion
//
/* [General] */
model = "all"; // [cube,ybar,tower,all]
center_models = false; // true / false
add_labels = true; // true / false
/* [Cube Dimensions] */
cube_x = 40;
cube_y = 40;
cube_z = 40;
/* [Y Bar Dimensions] */
ybar_x = 20;
ybar_y = 150;
ybar_z = 50;
/* [Tower Dimensions] */
tower_x = 18;
tower_y = 18;
tower_z = 120;
/* [Edge Treatment] */
corner_radius = 1.2; // 0 for sharp corners
$fn = 48;
/* [Labeling] */
label_depth = 0.6;
label_size = 7;
label_font = "Liberation Sans:style=Bold";
/* [Layout For model="all"] */
gap_between_models = 20;
// --------------------------------------------------
// Main
// --------------------------------------------------
if (model == "cube") {
make_cube();
}
else if (model == "ybar") {
make_ybar();
}
else if (model == "tower") {
make_tower();
}
else if (model == "all") {
make_all();
}
else {
echo("ERROR: model must be one of: cube, ybar, tower, all");
}
// --------------------------------------------------
// Assemblies
// --------------------------------------------------
module make_all() {
x0 = 0;
x1 = x0 + cube_x + gap_between_models;
x2 = x1 + ybar_x + gap_between_models;
translate([x0, 0, 0]) make_cube();
translate([x1, 0, 0]) make_ybar();
translate([x2, 0, 0]) make_tower();
}
module make_cube() {
difference() {
rounded_box(cube_x, cube_y, cube_z, corner_radius, center_models);
if (add_labels)
place_top_label("CUBE", cube_x, cube_y, cube_z, center_models);
}
}
module make_ybar() {
difference() {
rounded_box(ybar_x, ybar_y, ybar_z, corner_radius, center_models);
if (add_labels)
place_top_label("YBAR", ybar_x, ybar_y, ybar_z, center_models);
}
}
module make_tower() {
difference() {
rounded_box(tower_x, tower_y, tower_z, corner_radius, center_models);
if (add_labels)
place_top_label("TOWER", tower_x, tower_y, tower_z, center_models);
}
}
// --------------------------------------------------
// Geometry helpers
// --------------------------------------------------
module rounded_box(x, y, z, r=0, center_it=false) {
if (r <= 0) {
cube([x, y, z], center=center_it);
} else {
if (center_it) {
translate([-x/2, -y/2, -z/2])
rounded_box_uncentered(x, y, z, r);
} else {
rounded_box_uncentered(x, y, z, r);
}
}
}
module rounded_box_uncentered(x, y, z, r) {
linear_extrude(height=z)
offset(r=r)
offset(delta=-r)
square([x, y], center=false);
}
module place_top_label(txt, x, y, z, center_it=false) {
// --- parameters ---
margin = 2; // mm clearance from edges
// usable space
usable_x = x - margin;
usable_y = y - margin;
// choose orientation: run along long axis
rotate_text = (y > x);
// limiting width after orientation
limit = rotate_text ? usable_y : usable_x;
// crude text width estimate factor (~0.6 * size * chars)
est_char_width = 1.0;
est_len = len(txt) * est_char_width;
// compute size that fits
auto_size = limit / est_len;
// clamp to your preferred max size
final_size = min(label_size, auto_size);
// placement
tx = center_it ? 0 : x/2;
ty = center_it ? 0 : y/2;
tz = center_it ? z/2 : z;
translate([tx, ty, tz - label_depth])
rotate([0, 0, rotate_text ? 90 : 0])
linear_extrude(height=label_depth + 0.02)
text(
txt,
size=final_size,
font=label_font,
halign="center",
valign="center"
);
}
module place_top_labelOLD(txt, x, y, z, center_it=false) {
tx = center_it ? 0 : x/2;
ty = center_it ? 0 : y/2;
tz = center_it ? z/2 : z;
translate([tx, ty, tz - label_depth])
linear_extrude(height=label_depth + 0.02)
text(
txt,
size=label_size,
font=label_font,
halign="center",
valign="center"
);
}

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -0,0 +1,5 @@
sync_info = create
user_id =
setting_id =
base_id = OGFSL19
updated_time = 0

View file

@ -0,0 +1,16 @@
{
"compatible_printers": [
"Sovol SV06 ACE 0.4 nozzle"
],
"fan_cooling_layer_time": [
"20"
],
"filament_settings_id": [
"PolyLite PLA @System - Z-Tower"
],
"from": "User",
"inherits": "PolyLite PLA @System",
"is_custom_defined": "0",
"name": "PolyLite PLA @System - Z-Tower",
"version": "2.3.0.3"
}

View file

@ -0,0 +1,5 @@
sync_info = update
user_id =
setting_id =
base_id = GP004
updated_time = 0

View file

@ -0,0 +1,24 @@
{
"bottom_shell_layers": "5",
"brim_type": "outer_only",
"from": "User",
"inherits": "0.20mm Standard @Sovol SV06 ACE",
"initial_layer_line_width": "0.42",
"initial_layer_print_height": "0.2",
"inner_wall_speed": "80",
"is_custom_defined": "0",
"line_width": "0.42",
"name": "Y-bar_20260317_final",
"only_one_wall_top": "0",
"outer_wall_acceleration": "1500",
"outer_wall_line_width": "0.42",
"outer_wall_speed": "60",
"print_settings_id": "Y-bar_20260317_final",
"skirt_loops": "2",
"sparse_infill_density": "20%",
"sparse_infill_pattern": "gyroid",
"top_shell_layers": "5",
"top_solid_infill_flow_ratio": "1",
"version": "2.3.0.3",
"wall_loops": "3"
}

View file

@ -0,0 +1,5 @@
sync_info = update
user_id =
setting_id =
base_id = GP004
updated_time = 0

View file

@ -0,0 +1,26 @@
{
"bottom_shell_layers": "5",
"brim_type": "outer_only",
"from": "User",
"inherits": "0.20mm Standard @Sovol SV06 ACE",
"initial_layer_line_width": "0.42",
"initial_layer_print_height": "0.2",
"inner_wall_speed": "80",
"is_custom_defined": "0",
"line_width": "0.42",
"name": "Z-tower_20260317_final",
"notes": "Orca serialization note\n\nIn Orca Slicer 2.3.0.3, some live profile values may not appear in the saved process JSON even when they are active in the UI. For the Z-tower profile, Sparse infill density was verified in the live UI as 10% before slicing, even though the saved JSON did not include a sparse_infill_density key.\n\nScreenshot was taken showing the 10% value, 20260318_184351_Wed.png",
"only_one_wall_top": "0",
"outer_wall_acceleration": "1500",
"outer_wall_line_width": "0.42",
"outer_wall_speed": "40",
"print_settings_id": "Z-tower_20260317_final",
"seam_gap": "0",
"seam_position": "back",
"skirt_loops": "2",
"sparse_infill_pattern": "line",
"top_shell_layers": "5",
"top_solid_infill_flow_ratio": "1",
"version": "2.3.0.3",
"wall_loops": "3"
}

View file

@ -0,0 +1,5 @@
sync_info = create
user_id =
setting_id =
base_id = GP004
updated_time = 0

View file

@ -0,0 +1,23 @@
{
"bottom_shell_layers": "5",
"brim_type": "no_brim",
"from": "User",
"inherits": "0.20mm Standard @Sovol SV06 ACE",
"initial_layer_line_width": "0.42",
"initial_layer_print_height": "0.2",
"inner_wall_speed": "80",
"is_custom_defined": "0",
"line_width": "0.42",
"name": "cube_20260317_final",
"only_one_wall_top": "0",
"outer_wall_acceleration": "1500",
"outer_wall_line_width": "0.42",
"outer_wall_speed": "60",
"print_settings_id": "cube_20260317_final",
"seam_position": "back",
"skirt_loops": "2",
"sparse_infill_pattern": "grid",
"top_shell_layers": "5",
"top_solid_infill_flow_ratio": "1",
"version": "2.3.0.3"
}

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff