Tuesday, June 23, 2009

Tiny fonts with xorg (incorrect DPI)

Lots of monitors are totally screwed up in the way they report their sizes to your video card. So it's quite common to have insanely large or insanely tiny fonts for some graphical apps in linux.

Here's how I just fixed that on an Ubuntu Linux machine:

As root, edit /etc/X11/xorg.conf. In the "Section "Device"" part of the file that has your video card settings, put this so it won't try to get the DPI from the monitor:

Option "UseEdidDpi" "off"

Then, in the "Section "Monitor"", I added this line:

DisplaySize 508 286

That makes my 1920x1080 display use 96x96 dpi, a good common value.

This thread in the Arch linux forums lists this formula for the DisplaySize: displaysize = (/DPI-Desired)*25.4. So (1920/96)*25.4 = 508.

Save the file, restart X with control-alt-backspace, and see if it works.

ubuntu and libXm.so.3

If applications complain about not being able to find libXm.so.3, you should "sudo apt-get install libmotif3". (Hey, that rhymes)

Sunday, June 21, 2009

Sketchup bed design



Trying out ideas for a bed that would look nice, yet be easy to make on the shopbot. I'm thinking the curves could be simple v-groove engraved, and everything but the posts could be pre-finished cabinet plywood. It'd be neat to engrave some tasteful scrollwork on the faces too, just because it's so easy to do.

Here's the sketchup file: bed.skp.

Friday, June 19, 2009

Shopbot router tool bit holder



Today I built a really simple holder for my shopbot bits and collets. And here are the source files I used to build it: bit-holder.zip. It includes the sketchup model, .dxf, PartWorks V2 .crv file that generated the toolpath, and the .sbp shopbot partfile itself.

It's astounding how bad this workflow is. There are plenty of opportunities to make mistakes with each of the 4 different file formats, and every time I make a change to the sketchup file, I have to manually regenerate each of the following steps and try to remember what settings I used. Plus, each of the 3 programs has bugs that create headaches at best and dangerous situations and ruined parts during manufacturing at worst.

So the bugs need to get fixed regardless. Then there are two ways to make the process better: make the workflow shorter, so that at least there's a single UI for each of the steps, or make the tools more modular and configurable so that you can automate the process of stringing them together.

The former approach reminds me of "integrated development environments" for writing software, such as Microsoft's Visual Studio. Everything comes with a slick user interface, and debugging, compiling and project management are all built in. The downside is that you're stuck with that package of tools, and automating big tasks like rebuilding a huge software product don't usually work very well.

The latter approach reminds me of using Makefiles to build software. You have to do some work up front to define how the parts of your project get built. But once you've done that correctly, typing "make" is sufficient to automatically rebuild any parts of the project that have changed. Big software projects almost always use this approach, in my experience.

The latter approach is the one I'd prefer in this case. There are three distinct parts to manufacturing a part on a CNC machine like this: making the 3d model, defining the toolpaths (what type of cutting bit to use, what what type of cut to make, feed rates, etc.), and executing that toolpath on your particular machine. Each of those can be relatively independent and should be interchangeable. And ideally, they'd all be available as Free software.

So someday, I'd like to be able to build my part in Free Sketchup, look at the Free toolpath generator's idea of how to cut it, tweak a settings file to fix anything I don't like, and then do a quick check on my Shopbot Simulator to make sure it'll cut the way I expect. And then when I have to tweak some part of the model, I can just run "make" and get all the derivative files generated automatically.

Wednesday, June 17, 2009

Shopbot aluminum feeds & speeds

11 March 2010 update:

One note about cutting metal on the shopbot: I'm always careful to empty the dust collector before I start cutting. Don't want hot metal shavings flying into a cloud of wood dust!

Wow, cutting fluid really makes a difference. Today I cut some 1/4" 6-series aluminum plate with a 1/4" 2-flute carbide end mill. After each pass, I'd raise the head, vacuum out the chips and put a little stream of A-9 Aluminum Cutting Fluid all along the groove.

Here's what I got away with:

- 1/4" 2-flute carbide end mill (short bit -- I think it's a 1.25" flute length bit)
- 6000RPM
- 0.3 IPS (so 0.0015" chip load per flute)
- 0.060" depth of cut per pass

I found it helpful to do a dry pass to start at 0.010" depth, to outline where the groove would be and leave me a little channel for fluid for the first pass. It also showed me that my workpiece wasn't very flat with respect to the tool... :/

This chart proved handy. On some of my earlier runs, I was really pushing the recommended chip load limits.

(9 July update with more numbers)

I got some new, shorter end mills. The 1/4" 3-flute didn't sound great at the settings I liked before, so I turned down the depth-of-cut to 0.010 again (yargh):

UPDATE: ignore this set of numbers; after getting 0.050 or so into the material, the mills kept loading up. Sigh, back to the conservative numbers.

3-flute solid carbide end mill
10,000 rpm
1 ips
0.010" depth of cut
okay, a little whiny

4-flute solid carbide end mill
10,000 rpm
1 ips = 0.0015" chip load
0.010" depth of cut
very nice

4-flute solid carbide end mill
10,000 rpm
1 ips
0.020" depth of cut
not bad

4-flute solid carbide end mill
10,000 rpm
1 ips
0.030" depth of cut
a little whiny but not bad; eventually loaded up badly

4-flute solid carbide end mill
10,000 rpm
0.3 ips
0.030" depth of cut
much whinier, at 1/3 the feed rate!

4-flute solid carbide end mill
10,000 rpm
1 ips
0.050" depth of cut
whiny, then loaded up with material

4-flute solid carbide end mill
10,000 rpm
1 ips
0.020" depth of cut
this seems to be sustainable, but keep an eye on it

(Updated to fix ipm numbers)

We have a Shopbot PRS Alpha with a 2HP HSD spindle at work, and I've been experimenting with cutting aluminum on it. Here are my latest results:

All were short passes across the face of a 1/2" 6061 T6 aluminum plate (so watch for heat buildup for actual tasks). Note that the 6-series behaves MUCH differently from 5-series aluminum. I need to experiment more, but I think 5052 will be much better to mill on a shopbot than 6061.

Summary of max feed rates I felt comfortable with:

3-flute 1/4" solid carbide end mill:
6000 rpm
0.020" depth of cut
0.30 ips = 18 ipm = 0.001" per flute

1-flute onsrud spiral 1/4" cutter, 1.25" cut length.
I think I bought too long a bit so it chatters:
AVOID

1.25" 2-edge face cutter:
3000 rpm
0.005" depth
0.1 ips = 6 ipm = 0.001" per flute

2-flute 1/2" TiCN-coated solid carbide end mill:
12000 rpm
0.03" depth of cut
0.40 ips = 24 ipm = 0.001" per flute


Details:

3-flute 1/4" solid carbide end mill

3000 rpm
0.020" depth of cut
0.050 ips = 3 ipm = 0.000333" per flute
works good

3000 rpm
0.040" depth of cut
0.050 ips = 3 ipm
sounds bad; I think it's loading up

6000 rpm
0.020" depth of cut
0.10 ips = 6 ipm
seems okay

6000 rpm
0.020" depth of cut
0.20 ips = 12 ipm = 0.000666" per flute
seems okay

6000 rpm
0.020" depth of cut
0.30 ips = 18 ipm = 0.001" per flute
also okay

6000 rpm
0.020" depth of cut
0.30 ips = 18 ipm = 0.001" per flute
also okay

12000 rpm
0.020" depth of cut
0.60 ips = 36 ipm = 0.001" per flute
some vibration, maybe okay

18000 rpm
0.020" depth of cut
0.90 ips = 54 ipm = 0.001" per flute
tends to screech. do I smell something burning?


1-flute onsrud spiral 1/4" cutter, 1.25" cut length:

3000 rpm
0.020" depth of cut
0.050 ips = 3 ipm = 0.001" per flute
screechy chatter

6000 rpm
0.020" depth of cut
0.050 ips = 3 ipm = 0.0005" per flute
chatter twice as loud

12000 rpm
0.020" depth of cut
0.050 ips = 3 ipm = 0.00025" per flute
now sounds like "bizzity bizzity bizzity..."

18000 rpm
0.020" depth of cut
0.050 ips = 3 ipm = 0.000?" per flute
same but faster

12000 rpm
0.010" depth of cut
0.050 ips = 3 ipm = 0.00025" per flute
same but higher pitched


1.25" 2-edge face cutter:

3000 rpm
0.005" depth
0.05 ips = 3 ipm = 0.0005" per flute
not bad

3000 rpm
0.005" depth
0.1 ips = 6 ipm = 0.001" per flute
not bad. nice rainbow finish!

3000 rpm
0.010" depth
0.1 ips = 6 ipm = 0.001" per flute
some chatter but not bad.

6000 rpm
0.010" depth
0.2 ips = 12 ipm = 0.001" per flute
bigger c-shaped chips. occasional grindy noises


2-flute 1/2" tin-coated solid carbide end mill:

3000 rpm
0.020" depth of cut
0.050 ips = 3 ipm = 0.0005" per flute
quiet but unhappy screeches

6000 rpm
0.010" depth of cut
0.050 ips = 3 ipm = 0.00025" per flute
seems pretty happy

6000 rpm
0.010" depth of cut
0.10 ips = 6 ipm = 0.0005" per flute
starting to have some vibration

6000 rpm
0.010" depth of cut
0.20 ips = 12 ipm = 0.001" per flute
not bad

12000 rpm
0.010" depth of cut
0.40 ips = 24 ipm = 0.001" per flute
not bad

12000 rpm
0.015" depth of cut
0.40 ips = 24 ipm = 0.001" per flute
still not too bad

12000 rpm
0.03" depth of cut
0.40 ips = 24 ipm = 0.001" per flute
still okay

12000 rpm
0.05" depth of cut
0.40 ips = 24 ipm = 0.001" per flute
tends to whistle and vibrate

Sunday, June 14, 2009

Simple collapsible product photography rig










Here's an easy table saw project that breaks down into a set of flat panels for storage and transport.

Materials:

- 1 plastic light panel as a flash diffuser, available at your local hardware store or TAP plastics
- a 2 foot by 4 foot piece of white flexible plastic from TAP for the continuous backdrop
- (optional) 2 foot by 4 foot piece of adhesive-backed anti-reflective black flocking material, to stick on the back of the white plastic, making the backdrop black/white reversible
- about 2 feet by 5 feet of 3/4" cabinet-grade plywood

Table saw blades are about 1/8" thick, which is perfect to create the slots for the diffuser panels. I cut a slot about 1/4" deep to hold the upright piece of plywood. That slot has to be just the right width in order to hold the upright rigid. If you want something more secure, it's easy to cut two 1" wide, 2 foot long strips and put them on either side of the slot to effectively make it much deeper.

I used solid birch for the top and front slots that hold the backdrop in place, but plywood would work just as well.

Saturday, June 06, 2009

Determinant sudoku

Some friends of mine have trouble finding sufficiently difficult sudoku puzzles to keep them occupied. So one day while daydreaming I came up with Determinant Sudoku, in which you take the determinant of each square within a valid sudoku and make a super-square in which no row or column repeats a determinant.

In base-4 sudoku, such a Determinant Sudoku is a grid of 12x12 numbers, not too much larger than a base-10 ordinary sudoku. But I wasn't sure if any valid base-4 Determinant Sudoku actually existed, so I wrote a program to help me check.

I did manage to construct a valid base-4 Determinant Sudoku, but I'm not sure how many others exist.

Here is the source code to enumerate all base-4 sudoku and print their determinants, and I've copied the comment header below which includes more explanation and the base-4 determinant sudoku I found:


// This program enumerates all the base-4 sudoku and calculates
// their determinants.
//
// The idea is this: start with base-4 sudoku, so that you get
// 2x2 squares which have the numbers 0,1,2,3 with none repeated.
// Create a 2x2 grid of those 2x2 squares, so that each row and column
// has the numbers 0,1,2,3. (Ordinary sudoku, but 4x4 instead of 9x9).
//
// Here's an example of a valid base-4 sudoku:
// 01 23
// 23 01
//
// 10 32
// 32 10
//
// There appear to be 288 distint base-4 sudoku, without removing isomorphisms.
//
// My idea was to take the determinant of each of those 2x2 matrices and create
// a "determinant sudoku".
//
// In matrix math, the determinant of
// a b
// c d
// is a*d - b*c.
//
// There are six possible determinants of the 2x2 blocks.
//
// To construct a base-4 determinant-sudoku, make a 3x3 grid of 4x4 base-4
// sudoku blocks. There will be six rows and six columns of 2x2 squares.
//
// How many base-4 determinant-sudoku blocks exist?
// This program almost answers that question, but not quite.
//
// Of the 288 base-4 sudoku, 168 have the same determinant, leaving 120
// base-4 sudoku that could contribute to a base-4 determinant-sudoku.
//
// I constructed one base-4 determinant-sudoku by hand:
//
// 01 23 | 01 32 | 02 31
// 23 01 | 32 01 | 31 02
// | |
// 10 32 | 10 23 | 20 13
// 32 10 | 23 10 | 13 20
//
// ----------------------
//
// 01 32 | 02 31 | 01 23
// 32 01 | 31 02 | 23 01
// | |
// 10 23 | 20 13 | 10 32
// 23 10 | 13 20 | 32 10
//
// ----------------------
//
// 02 31 | 01 23 | 01 32
// 31 02 | 23 01 | 32 01
// | |
// 20 13 | 10 32 | 10 23
// 13 20 | 32 10 | 23 10
//
//
// Determinants:
//
// -2 2 -3 3 -6 6
// 2 -2 3 -3 6 -6
//
// -3 3 -6 6 -2 2
// 3 -3 6 -6 2 -2
//
// -6 6 -2 2 -3 3
// 6 -6 2 -2 3 -3
//
// Each 4x4 block is a valid base-4 sudoku. And the 6x6 grid of 2x2 blocks
// has no repeated determinants in any row or column.
//
// (This base-4 determinant sudoku isn't very nice, since it repeats the
// same 3 base-4 sudoku 3 times each.)
//
// So the question remains open: how many base-4 determinant sudoku are there?

Tuesday, June 02, 2009

Drill holes in objects using sketchup

If you've ever used sketchup for woodworking, you've probably noticed that it's a pain to drill holes in your workpieces. You have to create a circle, type in its diameter, then use the push/pull tool to push the hole through to the other side. Unfortunately, you can't make the hole a component, either, since it won't intersect right unless you explode it first.

So here's a ruby extension for drilling holes with a single click. Save the below code to a file called "drill.rb" in your Plugins/ directory. Open sketchup, go to Window... Preferences, click Extensions, and enable "Ruby Script Examples". Then you may need to restart sketchup to see the Plugins dropdown. Select "drill", type a hole diameter in the VCB and then hit enter. It'll save that value until you change it. Now click on a face on a 3d object to drill a hole through it.


# Hacked together from the linetool example by Jason E. Holt
# Copyright 2005-2008, Google, Inc.

# This software is provided as an example of using the Ruby interface
# to SketchUp.

# Permission to use, copy, modify, and distribute this software for
# any purpose and without fee is hereby granted, provided that the above
# copyright notice appear in all copies.

# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#-----------------------------------------------------------------------------

require 'sketchup.rb'

class Drill

@@drill_diameter = 1

# This is the standard Ruby initialize method that is called when you create
# a new object.
def initialize
end

def draw(view)
Sketchup::set_status_text "DIAMETER", SB_VCB_LABEL
Sketchup::set_status_text @@drill_diameter.to_s, SB_VCB_VALUE
end

# The activate method is called by SketchUp when the tool is first selected.
# it is a good place to put most of your initialization
def activate
Sketchup::set_status_text "DIAMETER", SB_VCB_LABEL
Sketchup::set_status_text @@drill_diameter.to_s, SB_VCB_VALUE
end

# The onLButtonDOwn method is called when the user presses the left mouse button.
def onLButtonDown(flags, x, y, view)
center_ip = Sketchup::InputPoint.new
center_ip.pick view, x, y
face = center_ip.face

center = center_ip.position
normal = face.normal

if ( face )
circle = view.model.entities.add_circle center, normal, @@drill_diameter / 2.0

other_entities = face.all_connected

reversed_normal = normal.reverse

circleface = nil

# This seems lame. add_circle seems to add it as a face, but then I have
# to go looking for that face.
for other in other_entities
if other.typename == "Face" and other.classify_point(center) == 1
#UI.messagebox("found myself :/")
circleface = other
end
end

# Find a face opposite the one they clicked in
for other in other_entities

#UI.messagebox("type is " + other.typename)

if other.typename == "Face"
if reversed_normal.samedirection? other.normal
#UI.messagebox "found it!"

point_on_other_face = center.project_to_plane other.plane
if other.classify_point(point_on_other_face) == 1
#UI.messagebox "yes, point projects onto other face."
pushpull_distance = point_on_other_face.vector_to(center).length

circleface.pushpull(-pushpull_distance)
else
#UI.messagebox "nope, doesn't project"
end
else
#UI.messagebox "nope"
end
end
end

view.model.commit_operation

else
UI.messagebox "Drilling only works on faces"
end
end

def onUserText(text, view)

# The user may type in something that we can't parse as a length
# so we set up some exception handling to trap that
begin
value = text.to_l
rescue
# Error parsing the text
UI.beep
puts "Cannot convert #{text} to a Diameter"
value = nil
Sketchup::set_status_text "", SB_VCB_VALUE
end
return if !value

@@drill_diameter = value
end

end # class Drill

#-----------------------------------------------------------------------------
# This functions is just a shortcut for selecting the new tool
def drill
Sketchup.active_model.select_tool Drill.new
end

UI.menu("PlugIns").add_item("Drill") {
drill
}