You can buy new plotter pens for HP 7475A plotters at a bit over four bucks apiece and new-old-stock HP pens appear on eBay with similar prices, but what’s the fun in that?
You can refill the HP pens with liquid ink and continue plotting until the fiber tip wears out. That would limit me to the CMYK inkjet inks on the shelf, although I suppose investing in drafting inks might be amusing.
You can get refillable Koh-I-Noor pens and adapters, intended for specialized paper / vellum, at nearly $100 all-in per pen, plus ink & supplies, plus a hassle factor exceeding that of the continuous flow ink system on the Epson R380.
However, it should be feasible to build an adapter to hold an ordinary, albeit skinny, drawing / drafting pen, perhaps chopped down to be only a bit longer than the OEM plotter pens. That has the advantage of using cheap & readily available materials, doesn’t require much capital outlay, and, come to think of it, gives me a Digital Machinist column topic… [grin]
This is not, by any stretch of the imagination, a novel idea.
There’s a vague notion of converting the plotter into a vinyl / paper / stencil cutter, although I expect the snap-in pen holder can’t exert enough lateral force to hold a cutting knife in position, nor enough downward force to push the blade through the vinyl / paper / whatever. But ya never know until you try.
So, we begin…
A bit of digital caliper work provides a list of points defining the OEM pen body outline:
RADIUS = 0; // subscript for radius values HEIGHT = 1; // ... height above Z=0 BodyOutline = [ // X values = (measured diameter)/2, Y as distance from tip [0.0,0.0], // 0 fiber pen tip // [2.0/2,1.4], // 1 ... taper (not buildable) [1.0/2,0.005], // 1 ... faked point to remove taper [2.0/2,0.0],[2.0/2,2.7], // 2 ... cylinder [3.7/2,2.7],[3.7/2,4.45], // 4 tip surround [4.8/2,5.2], // 6 chamfer [6.5/2,11.4], // 7 rubber seal face [8.9/2,11.4], // 8 cap seat [11.2/2,15.9], // 9 taper to body [11.5/2,28.0], // 10 lower body [13.2/2,28.0],[16.6/2,28.5], // 11 lower flange = 0.5 [16.6/2,29.5],[13.2/2,30.0], // 13 flange rim = 1.0 [11.5/2,30.0], // 15 upper flange = 0.5 [11.5/2,43.25], // 16 upper body [0.0,43.25] // 17 lid over reservoir ];
Rather than computing the radius by hand, it’s easier to just divide the easily measured diameter by two and be done with it.
The point array defines a polygon in the XY plane:

Then you feed that polygon into a rotate_extrude()
, which spins up a reasonable simulacrum of a plotter pen:

I picked the coordinates to put the tip at (0,0,0) and converted the tapered fiber nib into a plain cylinder.
That shape is obviously impossible to print without vast amounts of support, but splitting it across the middle of the flange and rearranging the pieces works just fine:

A pair of alignment pin holes simplifies gluing the parts back together:

There’s a subtle problem lurking in that flange, which is 2.0 mm thick at the base and 1.0 mm thick at the rim. Splitting it in half requires each part to build correctly from an integral number of thread layers, so you must use a thread thickness (that’s in the Z direction) that divides evenly into the required height. I’ve been using 0.2 mm, which would produce a 1.2 mm rim.
Slicing at 0.25 mm produced a 2.1 mm flange with a 1.1 mm rim, suggesting that:
- The first layer is 0.05 mm too thick, slightly more than suggested by the skirts
- The glued joint isn’t 0.00 mm thick
- Some combination or permutation of those
I could apply a Slic3r Modifier Mesh to print the flange with 0.10 mm layers, but that seems like entirely too much effort right now.
At the other end of the model, converting the tapered tip into a blunt cylinder didn’t save it from melting down:

It might be possible to reduce the printing speed enough to produce that tiny cylinder, but I needed just the upper body to verify that it fit correctly into the carousel:

As you’d expect, the rubber boots that used to seal the pen tips have long since rotted out:

You can find sources for those boots, but at $252 (marked down to $144!) each, perhaps it’d be more feasible to gimmick up a two-part mold and cast silicone rubber duplicates; I could sell a set of six for $200 and get rich. Heck, I could even undercut their $40.32 two-year protection plan by a considerable margin.
Anyhow, the pen holder plucked it out of the carousel just like a real HP pen:

Note that the carousel and pen holder contact the flange and the cylindrical body, not either of the tapered sections down to the tip. That means I can carve away the entire bottom part of the body to make a drawing pen adapter…
The OpenSCAD source code includes a bunch of features & parts I’ll describe in the next few posts, but which certainly should not be regarded as final copy:
// HP7475A plotter pen adapters // Ed Nisley KE4ZNU April 2015 Layout = "BuildBody"; // ShowKnife BuildKnife KnifeAdapter // ShowPen BuildPen Plug // ShowBody BuildBody // Pen Knife // Stabilizer BuildStabilizer //- Extrusion parameters must match reality! ThreadThick = 0.25; ThreadWidth = 0.40; HoleWindage = 0.2; Protrusion = 0.1; // make holes end cleanly inch = 25.4; function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); //---------------------- // Dimensions // Z=0 at pen tip! NumSides = 8*4; // number of sides on each "cylinder" RADIUS = 0; // subscript for radius values HEIGHT = 1; // ... height above Z=0 //-- Original HP plotter pen, which now serves as a body for the actual pen BodyOutline = [ // X values = (measured diameter)/2, Y as distance from tip [0.0,0.0], // 0 fiber pen tip // [2.0/2,1.4], // 1 ... taper (not buildable) [1.0/2,0.005], // 1 ... faked point to remove taper [2.0/2,0.0],[2.0/2,2.7], // 2 ... cylinder [3.7/2,2.7],[3.7/2,4.45], // 4 tip surround [4.8/2,5.2], // 6 chamfer [6.5/2,11.4], // 7 rubber seal face [8.9/2,11.4], // 8 cap seat [11.2/2,15.9], // 9 taper to body [11.5/2,28.0], // 10 lower body [13.2/2,28.0],[16.6/2,28.5], // 11 lower flange = 0.5 [16.6/2,29.5],[13.2/2,30.0], // 13 flange rim = 1.0 [11.5/2,30.0], // 15 upper flange = 0.5 [11.5/2,43.25], // 16 upper body [0.0,43.25] // 17 lid over reservoir ]; TrimHeight = BodyOutline[9][HEIGHT]; // cut off at top of lower taper SplitHeight = (BodyOutline[11][HEIGHT] + BodyOutline[14][HEIGHT])/2; // middle of flange FlangeOD = 2*BodyOutline[13][RADIUS]; FlangeTop = BodyOutline[15][HEIGHT]; BodyOD = 2*BodyOutline[16][RADIUS]; BodyOAL = BodyOutline[17][HEIGHT]; echo(str("Trim: ",TrimHeight)); echo(str("Split: ",SplitHeight)); BuildSpace = FlangeOD; //-- Sakura Micron fiber-point pen ExpRP = 0.15; // expand critical sections (by radius) //-- pen locates in holder against end of outer body PenOutline = [ [0,0], // 0 fiber pen tip [0.6/2,0.0],[0.6/2,0.9], // 1 ... cylinder [1.5/2,0.9],[1.5/2,5.3], // 3 tip surround [4.7/2,5.8], // 5 chamfer [4.9/2,12.3], // 6 nose // [8.0/2,12.3],[8.0/2,13.1], // 7 latch ring // [8.05/2,13.1],[8.25/2,30.5], // 9 actual inner body [8.4/2 + ExpRP,12.3],[8.4/2 + ExpRP,30.5], // 7 inner body - clear latch ring [9.5/2 + ExpRP,30.5], // 9 outer body - location surface! [9.8/2 + ExpRP,50.0], // 10 outer body - length > Body [7.5/2,50.0], // 11 arbitrary length [7.5/2,49.0], // 12 end of reservoir [0,49.0] // 13 fake reservoir ]; PenNose = PenOutline[6]; PenLatch = PenOutline[7]; PenOAL = PenOutline[11][HEIGHT]; PlugOutline = [ [0,0], // 0 center of lid [9.5/2,0.0],[9.5/2,1.0], // 1 lid rim [7.8/2,1.0], // 3 against end of pen [7.3/2,6.0], // 4 taper inside pen [5.3/2,6.0], // 5 against ink reservoir [4.0/2,1.0], // 6 taper to lid [0.0,1.0] // 7 flat end of taper ]; PlugOAL = PlugOutline[5][HEIGHT]; // cap locates against end of inner body at latch ring //-- cap origin is below surface to let pen tip be at Z=0 CapGap = 1.0; // gap to adapter body when attached CapGripHeight = 2.0; // thickness of cap grip flange CapTipClearance = 1.0; // clearance under fiber tip CapOffset = -(CapGripHeight + CapTipClearance); // align inside at pen tip Z=0 CapOutline = [ [0,CapOffset], // 0 base [FlangeOD/2,CapOffset], // 1 finger grip flange [FlangeOD/2,CapOffset + CapGripHeight], // 2 ... top [BodyOD/2,CapOffset + CapGripHeight], // 3 shaft [BodyOD/2,TrimHeight - CapGap], // 4 ... top with clearance [PenLatch[RADIUS],TrimHeight - CapGap], // 5 around pen latch ring [PenLatch[RADIUS],PenNose[HEIGHT]], // 6 ... location surface! [PenNose[RADIUS] + ExpRP,PenNose[HEIGHT]], // 7 snug around nose [PenNose[RADIUS] + ExpRP,-CapTipClearance], // 8 clearance around tip [0,-CapTipClearance], // 9 ... bottom ]; //-- Drag knife holder ExpRK = 0.30; // expand critical sections (by radius) AdjLen = 2.0; // allowance for adjustment travel KnifeOutline = [ [0,0], // 0 blade point (actually 0.25 mm offset) [1.0/2,0.0], // 1 ... blunt end [1.0/2,4.0], // 2 ... cylinder [2.0/2,4.0], // 3 shank [2.0/2,5.9], // 4 .. at bearing [6.0/2,5.9], // 5 holder - shell [7.3/2 + ExpRK,8.3], // 6 holder - taper to body [7.3/2 + ExpRK,21.0 - AdjLen], // 7 holder body [8.8/2 + ExpRK,22.0 - AdjLen], // 8 holder - threads bottom [8.8/2 + ExpRK,25.0],[9.0/2 + ExpRK,26.0], // 9 clear threads to reduce friction [9.0/2 + ExpRK,32.0],[8.8/2 + ExpRK,33.0], // 11 ... end clearance [8.8/2 + ExpRK,42.5 - AdjLen], // 13 holder - threads top = locknut bottom [12.5/2,42.5 - AdjLen], // 14 knurled locknut - adjustment travel [12.5/2,45.8], // 15 knurled locknut - top [11.0/2,45.8], // 16 holder - adjusting knurl [11.0/2,52.0], // 17 holder - top surface [3.0/2,52.0],[3.0/2,57.2], // 18 spring post [0.0,57.2] // 19 end of post ]; ThreadLength = KnifeOutline[13][HEIGHT] - KnifeOutline[8][HEIGHT]; //-- Plotter pen holder stabilizer HolderPlateThick = 3.0; // thickness of plate atop holder RimHeight = 5.0; // rim around sides of holder RimThick = 2.0; HolderOrigin = [17.0,12.2,0.0]; // center of pen relative to polygon coordinates HolderZOffset = 30.0; // top of holder in pen-down position HolderTopThick = 1.7; // top of holder to top of pen flange HolderCylinderLength = 17.0; // length of pen support structure HolderKnifeOffset = -2.0; // additional downward adjustment range (not below top surface) LockScrewInset = 3.0; // from right edge of holder plate LockScrewOD = 2.0; // tap for 2.5 mm screw // Beware: update hardcoded subscripts in Stabilizer() when adding / deleting point entries HolderPlate = [ [8.6,18.2],[8.6,23.9], // 0 lower left corner of pen recess [13.9,23.9],[13.9,30.0], // 2 // [15.5,30.0],[15.5,25.0], // 4 omit middle of support beam // [20.4,25.0],[20.4,30.0], // 6 [22.7,30.0],[22.7,27.5], // 4 [35.8,27.5],[35.8,20.7], // 6 spring box corner [43.0,20.7], // 8 [31.5,0.0], // 9 // [24.5,0.0],[24.5,8.0], // 10 omit pocket above pen clamp // [22.5,10.0],[22.5,16.5], // 12 // [20.5,18.2] // 14 [13.6,0.0], // 10 [8.6,5.0] // 11 ]; BeamWidth = HolderPlate[4][0] - HolderPlate[2][0]; //---------------------- // Useful routines module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2); FixDia = Dia / cos(180/Sides); cylinder(r=(FixDia + HoleWindage)/2, h=Height, $fn=Sides); } //- Locating pin hole with glue recess // Default length is two pin diameters on each side of the split PinOD = 1.75; PinOC = BodyOD / 2; module LocatingPin(Dia=PinOD,Len=0.0) { PinLen = (Len != 0.0) ? Len : (4*Dia); translate([0,0,-ThreadThick]) PolyCyl((Dia + 2*ThreadWidth),2*ThreadThick,4); translate([0,0,-2*ThreadThick]) PolyCyl((Dia + 1*ThreadWidth),4*ThreadThick,4); translate([0,0,-(Len/2 + ThreadThick)]) PolyCyl(Dia,(Len + 2*ThreadThick),4); } module LocatingPins(Length) { for (i=[-1,1]) translate([0,i*PinOC/2,0]) rotate(180/4) LocatingPin(Len=Length); } //---------------------- // Basic shapes //-- HP plotter pen body module Body() { render(convexity=3) rotate_extrude($fn=NumSides) polygon(points=BodyOutline); } //-- HP plotter pen holder // the trim block offsets use magic numbers from the HolderPlate outline module Stabilizer() { difference() { union() { translate(-HolderOrigin) // put center of pen at origin difference() { render(convexity=4) linear_extrude(height=(HolderPlateThick + RimHeight)) // overall flange around edges offset(r=RimThick) polygon(points=HolderPlate); render(convexity=4) translate([0,0,-Protrusion]) // recess for pen holder plate linear_extrude(height=(RimHeight + Protrusion)) polygon(points=HolderPlate); translate([HolderPlate[7][0] - Protrusion,HolderPlate[7][1] - Protrusion,-Protrusion]) // trim spring box from top plate cube([30,20,(RimHeight + HolderPlateThick + 2*Protrusion)]); translate([27.0,HolderPlate[6][1] - Protrusion,-Protrusion]) // trim pivot plate clearance cube([30,20,(RimHeight + HolderPlateThick + 2*Protrusion)]); translate([HolderPlate[2][0],20,-Protrusion]) // trim left support beam cube([BeamWidth,20,(RimHeight + Protrusion)]); translate([HolderPlate[9][0] - LockScrewInset,RimThick,RimHeight - HolderTopThick - LockScrewOD/2]) // lock screw on front edge rotate([90,0,0]) rotate(180/4) PolyCyl(LockScrewOD,3*RimThick); // hold-down screw hole } translate([0,0,(RimHeight - HolderCylinderLength + Protrusion)]) cylinder(d=BodyOD,h=HolderCylinderLength + Protrusion,$fn=NumSides); // surround knife threads } translate([0,0,-HolderZOffset + HolderKnifeOffset]) Knife(); } } //-- Sakura drawing pen body module Pen() { rotate_extrude($fn=NumSides) polygon(points=PenOutline); } //-- Plug for top of Sakura pen module Plug() { render(convexity = 2) rotate_extrude($fn=NumSides) polygon(points=PlugOutline); } //-- Cap for tip of Sakura pen module Cap() { render(convexity = 2) rotate_extrude($fn=NumSides) polygon(points=CapOutline); } //-- Sakura pen adapter module PenAdapter(TrimZ = false) { Trans = TrimZ ? - TrimHeight : 0; render(convexity=5) translate([0,0,Trans]) difference() { Body(); Pen(); translate([0,0,TrimHeight/2]) cube([2*FlangeOD,2*FlangeOD,TrimHeight],center=true); } } //-- Roland knife body module Knife() { render(convexity=3) rotate_extrude($fn=NumSides) polygon(points=KnifeOutline); } //-- Roland knife adapter module KnifeAdapter(TrimZ = false) { Trans = TrimZ ? - TrimHeight : 0; render(convexity=5) translate([0,0,Trans]) difference() { Body(); Knife(); translate([0,0,TrimHeight/2]) cube([2*FlangeOD,2*FlangeOD,TrimHeight],center=true); } } //---------------------- // Build it if (Layout == "Pen") Pen(); if (Layout == "Knife") Knife(); if (Layout == "Stabilizer") Stabilizer(); if (Layout == "ShowBody") Body(); if (Layout == "BuildBody") difference() { union() { translate([BuildSpace,0,-SplitHeight]) Body(); rotate([180,0,0]) translate([-BuildSpace,0,-SplitHeight]) Body(); } translate([0,0,-BodyOAL]) cube(2*BodyOAL,center=true); for (i = [-1,1]) translate([i*BuildSpace,0,0]) LocatingPins(5.0); } if (Layout == "Plug") Plug(); if (Layout == "KnifeAdapter") KnifeAdapter(); if (Layout == "ShowPen") { color("AntiqueWhite") { Pen(); translate([-1.5*BodyOD,0,0]) Pen(); } color("Magenta",0.35) { translate([0,0,PlugOAL + PenOAL + 3.0]) rotate([180,0,0]) Plug(); PenAdapter(); Cap(); } color("Magenta") { translate([1.5*BodyOD,0,PlugOAL + PenOAL + 3.0]) rotate([180,0,0]) Plug(); translate([1.5*BodyOD,0,0]) { PenAdapter(); Cap(); } } } if (Layout == "ShowKnife") { color("Goldenrod") { Knife(); translate([-1.5*BodyOD,0,0]) Knife(); } color("Magenta",0.35) KnifeAdapter(); color("Magenta") { translate([1.5*BodyOD,0,0]) KnifeAdapter(); } } if (Layout == "BuildPen") { translate([0,BuildSpace/2,0]) Plug(); translate([0,-BuildSpace/2,-CapOffset]) Cap(); difference() { union() { translate([BuildSpace,0,-SplitHeight]) PenAdapter(false); rotate([180,0,0]) translate([-BuildSpace,0,-SplitHeight]) PenAdapter(false); } translate([0,0,-BodyOAL]) cube(2*BodyOAL,center=true); } } if (Layout == "BuildKnife") { difference() { union() { translate([BuildSpace,0,-SplitHeight]) KnifeAdapter(false); rotate([180,0,0]) translate([-BuildSpace,0,-SplitHeight]) KnifeAdapter(false); } translate([0,0,-BodyOAL]) cube(2*BodyOAL,center=true); } } if (Layout == "BuildStabilizer") { translate([0,0,(HolderPlateThick + RimHeight)]) rotate([0,180,0]) Stabilizer(); }
One thing I considered before I gave mine away was replacing the pen with a powerful laser diode and lense, and using it as a laser cutter. It would only cut cloth, paper, and perhaps thin cardboard, but cutting with light avoids all the torque/drag/backlash issues with a knife. I figured I could grab the pen up/down signal and use it to turn the laser on and off.
CAUTION: Do not look into laser beam with remaining eye!
I’ve seen YouTube videos of such things and one could probably (although nobody does) conjure a baffle around the laser, but …
Also, it seem having a air / gas stream blowing the smoke away from the optics is a Good Thing, so there’s a chunk of tubing flopping around with the laser wires, too.
It might actually work!
It does: I ended up doing that briefly with my 7470. I used a microswitch to turn it on and off. If I had to do it again I think I’d splice into the pen up/down electrics.
The drag was that on anything light-colored, the laser wouldn’t start burning fast enough. Once there’s a black spot everything’s fine, it runs that spot right along, but you have to dwell for about half a second at the first point to get it started. That’s one reason I went to doing this all in the mill, where I can use a digital output to control the laser, and use pauses to give it time to get the spot started.
(both machines do a nice job of cutting gasket material for engines: it’s dark enough to start burning immediately, and when it gets done I can just snap them out. But the mill is so much more convenient.)
I took a different tack, and bought one of those cheap Chinese laser cutters with a 40 watt CO2 laser. First thing, I repaired the laser power supply. Then, I replaced the control electronics with an EiBot board, so I could actually talk to it (the electronics it came with contained already-oozing capacitors, and a Champ-36 connector apparently intended to connect to a line printer port using an undocumented protocol). Now can run the laser cutter directly from InkScape over an ordinary USB connection. I’m currently in the process of adding air assist to blow the smoke away as well as encourage melted acrylic to not stick around.
Looks like Amazon has them for $500-ish these days. The reviews suggest the cutter arrives as a shop project, but if you can get past that, it works reasonably well.
I’m not quite ready for one right now, but it seems more do-able (albeit much smaller) than a Lasersaur and much, much safer than the “clip a laser diode to your Reprap printer” products on Amazon… [sigh]
How does this step work? Is it behaving as a system-recognized printer, or do you have an inkscape plugin that drives it directly?
There’s an InkScape plugin (written in Python) that drives it directly. The laser cutter has a X and Y homing switches, so I’m thinking of modifying the plugin to jog to a known position before cutting. Fortunately, the EiBot board is based on the USB BitWhacker, and supports those functions as well, so I can monitor input leads for switch closures.