Read this model as text
A wall holder for one paper roll. Two identical brackets screw to the wall, each with one arm that carries an open-top slot. A rod goes through the core of the roll and drops into the slots from above, guided by a funnel at the slot entry. Printed end caps keep the rod from wandering sideways.
The image shows the solid OpenSCAD renders at part assembly · roll_diameter 100 · paper_width 1000 · rod_diameter 20 · bracket_width 22 · screw_diameter 4.5 · color_print SteelBlue.
Wall holder for a paper roll
mick/paper-roll-holder@1.0.0
Report
For a legal or policy problem: a license violation, personal data, somebody else’s work republished as their own. A model that prints badly is a comment, not a report.
Parameters
from sourceDescription
What is this
A wall holder for one paper roll. Two identical brackets screw to the wall, each with one arm that carries an open-top slot. A rod goes through the core of the roll and drops into the slots from above, guided by a funnel at the slot entry. Printed end caps keep the rod from wandering sideways.
What you use it for
Keeping a roll of brown paper (kraft paper) ready on the wall, for workshops, wrapping or the workbench. Changing the roll takes no tools: lift the rod out, slide the new roll on and drop it back in.
Design notes
The bracket is one 2D profile of axis-aligned squares: a back plate with the arm in the middle, a wall screw above and below it. Rounding never shapes the design, it only polishes it: an offset pair rounds the profile corners and the extrusion gets a small 45 degree chamfer on both faces, which also takes care of elephant foot.
Print the bracket on its side, so the layers run along the arm instead of across it. Left and right are the same part, print it twice.
The slot sits 10 mm plus half the roll diameter from the wall, so a full roll just clears it. Only the five sizes that differ per situation are exposed, everything else is fixed in the source under Hidden.
The rod is not printed. Use a wooden dowel or a metal tube from the hardware store, cut to paper_width + 82 mm at the default bracket width (1082 mm for 1 m paper). For 1 m rolls a metal tube or a 25 mm dowel sags less than a 20 mm dowel. The caps take an axial wood screw into a dowel, on a tube a drop of glue does the same.
Parameters
part picks the assembly, one bracket laid down for printing, or one cap. roll_diameter is the largest full roll. paper_width only sizes the preview and the rod. rod_diameter sizes the slot and the caps. bracket_width is the width of the bracket along the wall. screw_diameter is the hole for the wall screws, the countersink follows it. color_print is display only.
Use with your agent
{
"mcpServers": {
"remixcad": {
"type": "http",
"url": "https://remix-cad.vercel.app/api/mcp"
}
}
}get_model("mick/paper-roll-holder@1.0.0")Returns the manifest, the source, the import closure and the license obligations. Full MCP setup.
Parameter table
Parsed from the Customizer annotations in main.scad| Name | Default | Range | Unit | Description |
|---|---|---|---|---|
| part | "assembly" | assembly, bracket, cap | ||
| roll_diameter | 100 | 40 to 250 step 5 | ||
| paper_width | 1000 | 200 to 1600 step 10 | ||
| rod_diameter | 20 | 8 to 35 step 1 | ||
| bracket_width | 22 | 14 to 40 step 1 | ||
| screw_diameter | 4.5 | 3 to 6 step 0.5 | ||
| color_print | "SteelBlue" | SteelBlue, White, Gainsboro, Silver, DimGray, Black, SlateGray, FireBrick, ForestGreen, Goldenrod |
Lineage
0 models depend on this oneOnly what this model came from and what came from it.
License
Whoever downloads this takes these obligations along- mick/paper-roll-holder@1.0.0 is MIT
Source
main.scad is the entrypointmain.scad
// A wall holder for one paper roll (brown paper / kraft paper). Two identical brackets,
// each with one arm carrying an open-top slot. A rod through the roll core drops into
// the slots from above. Built from straight rectangles; corners and edges are polished
// afterwards as a final step, never as part of the construction.
/* [Parts] */
// Render the assembly, or one part laid down for printing.
part = "assembly"; // [assembly, bracket, cap]
/* [Sizes] */
// Largest diameter of a full roll.
roll_diameter = 100; // [40:5:250]
// Width of the paper. Only sizes the preview and the rod length.
paper_width = 1000; // [200:10:1600]
// Diameter of the rod through the roll core.
rod_diameter = 20; // [8:1:35]
// Width of the bracket along the wall. This is the print height.
bracket_width = 22; // [14:1:40]
// Hole diameter for the wall screws. The countersink follows it.
screw_diameter = 4.5; // [3:0.5:6]
/* [Colour] */
// Colour the printed parts are shown in. Display only, the STL carries no colour.
color_print = "SteelBlue"; // [SteelBlue, White, Gainsboro, Silver, DimGray, Black, SlateGray, FireBrick, ForestGreen, Goldenrod]
/* [Hidden] */
rod_fit = 0.6; // spare room for the rod in the slot
back_t = 8; // back plate thickness
under = 12; // material under the rod
lip = 10; // lip in front of the slot
rise = 6; // arm height above the top of the rod
funnel = 5; // funnel at the slot entry
wall_gap = 10; // room between a full roll and the wall
tab = 24; // back plate above and below the arm, for the screws
round_r = 3; // profile corner polish
chamfer = 1.2; // face edge polish
smoothness = 48;
cap_wall = 5;
cap_depth = 12;
cap_fit = 0.3;
cap_screw_d = 3.5;
cap_end = 4;
head_d = 2 * screw_diameter;
slot_w = rod_diameter + rod_fit;
arm_h = under + rod_diameter + rise;
// The slot never cuts into the back plate, however small the roll.
seat_x = max(wall_gap + roll_diameter / 2, back_t + slot_w / 2 + 6);
reach = seat_x + slot_w / 2 + lip;
height = arm_h + 2 * tab;
seat_z = tab + under + rod_diameter / 2;
side_gap = 5;
play = 2;
bracket_y = paper_width / 2 + side_gap + bracket_width / 2;
rod_len = 2 * (bracket_y + bracket_width / 2 + play + cap_depth);
core_id = max(rod_diameter + 2, min(rod_diameter + 20, roll_diameter * 0.5));
echo(str("Rod length: ", rod_len, " mm"));
echo(str("Bracket: ", reach, " x ", height, " x ", bracket_width, " mm"));
// The polish: a closing pass rounds the concave corners, an opening pass the convex
// ones. Applied over the finished straight shape, never during it.
module polish2d(r) {
if (r > 0)
offset(r = r, $fn = smoothness)
offset(r = -2 * r, $fn = smoothness)
offset(r = r, $fn = smoothness)
children();
else
children();
}
// Extrude with a 45 degree chamfer on both faces, built from thin slices so it stays
// fast. One slice per 0.2 mm, the same as a print layer.
module polish_extrude(h, c) {
if (c > 0) {
n = ceil(c / 0.2);
s = c / n;
translate([0, 0, c]) linear_extrude(height = h - 2 * c) children();
for (i = [0 : n - 1]) {
inset = c - (i + 0.5) * s;
translate([0, 0, i * s])
linear_extrude(height = s + 0.001) offset(delta = -inset) children();
translate([0, 0, h - (i + 1) * s - 0.001])
linear_extrude(height = s + 0.001) offset(delta = -inset) children();
}
} else {
linear_extrude(height = h) children();
}
}
// ---- Bracket ----
// One 2D profile of axis-aligned squares, in the XZ plane.
// Origin: the wall at x = 0, the underside of the back plate at z = 0.
module profile_raw() {
// Back plate against the wall.
square([back_t, height]);
difference() {
// The arm, in the middle of the plate.
translate([0, tab]) square([reach, arm_h]);
// The slot, open at the top, with a round seat for the rod.
translate([seat_x, tab + under + slot_w / 2]) {
circle(d = slot_w, $fn = smoothness);
translate([-slot_w / 2, 0]) square([slot_w, arm_h]);
}
// The funnel, so the rod finds the slot when it drops in from above.
translate([seat_x, tab + arm_h])
polygon([[-slot_w / 2 - funnel, 1], [slot_w / 2 + funnel, 1],
[slot_w / 2 + funnel, 0], [slot_w / 2, -funnel],
[-slot_w / 2, -funnel], [-slot_w / 2 - funnel, 0]]);
}
}
module profile() {
polish2d(round_r) profile_raw();
}
module wall_screw(z) {
cs = (head_d - screw_diameter) / 2;
translate([-1, 0, z]) rotate([0, 90, 0])
cylinder(d = screw_diameter, h = back_t + 2, $fn = 32);
translate([back_t - cs, 0, z]) rotate([0, 90, 0])
cylinder(d1 = screw_diameter, d2 = head_d, h = cs + 0.01, $fn = 32);
translate([back_t, 0, z]) rotate([0, 90, 0])
cylinder(d = head_d, h = 2, $fn = 32);
}
module bracket() {
difference() {
translate([0, bracket_width / 2, 0])
rotate([90, 0, 0])
polish_extrude(bracket_width, chamfer) profile();
// One screw below the arm, one above it.
wall_screw(tab / 2);
wall_screw(height - tab / 2);
}
}
// ---- Rod end cap ----
// A cup over the rod end, wider than the slot, so the rod cannot wander sideways.
module cap() {
R = rod_diameter / 2 + cap_wall;
rb = (rod_diameter + cap_fit) / 2;
H = cap_end + cap_depth;
c = chamfer;
sr = cap_screw_d / 2;
difference() {
rotate_extrude($fn = smoothness)
polygon([[sr, 0], [R - c, 0], [R, c], [R, H - c], [R - c, H],
[rb, H], [rb, cap_end], [sr, cap_end]]);
translate([0, 0, -0.01])
cylinder(d1 = 2 * cap_screw_d, d2 = cap_screw_d, h = cap_screw_d / 2, $fn = 32);
}
}
// ---- Preview only: rod and roll ----
module rod() {
translate([seat_x, rod_len / 2, seat_z]) rotate([90, 0, 0])
cylinder(d = rod_diameter, h = rod_len, $fn = smoothness);
}
module roll() {
// The roll hangs on the rod by its core, so it sits a little lower than the rod.
translate([seat_x, paper_width / 2, seat_z - (core_id - rod_diameter) / 2])
rotate([90, 0, 0])
difference() {
cylinder(d = roll_diameter, h = paper_width, $fn = smoothness);
translate([0, 0, -1])
cylinder(d = core_id, h = paper_width + 2, $fn = smoothness);
}
}
// ---- Layout ----
if (part == "bracket") {
// On its side, ready to print. Print it twice, left and right are the same.
color(color_print) translate([0, 0, bracket_width / 2]) rotate([90, 0, 0]) bracket();
} else if (part == "cap") {
color(color_print) cap();
} else {
for (s = [-1, 1])
color(color_print) translate([0, s * bracket_y, 0]) bracket();
color("SaddleBrown") rod();
color(color_print) translate([seat_x, rod_len / 2 + cap_end, seat_z])
rotate([90, 0, 0]) cap();
color(color_print) translate([seat_x, -(rod_len / 2 + cap_end), seat_z])
rotate([-90, 0, 0]) cap();
color("Tan") roll();
}
Comments
Context, not a score. Comments never move a model up or down the results.No comments yet
Printed it? A note about your material and the clearance you landed on saves the next person a failed print.
