Friday, December 23, 2011

Diagnosing and fixing a misbehaving axis

Here's a story about a learning experience I had with my CNC3040 router. I'm documenting it here in the hope it helps someone else avoid my mistakes.

One day, in the middle of a light routing job, the X axis suddenly went crazy. It started stuttering and wandering about and generally doing anything else than what it was supposed to do. My first thought was that the driver board had fried. After all, that is something cheap Chinese drivers are known to do. A simple test seemed to confirm my hypothesis. I swapped X and Y axis cables and drove the axis back and forth a little and it seemed to work fine. (Mistake #1: I didn't test the axis at different speeds and accelerations)

So I logged on to eBay and ordered a replacement driver for $10. Once it arrived and I finally got around to replacing it, the axis continued to misbehave. I tested the axes more thoroughly this time and, indeed, the X axis didn't work right with any driver of other drivers either. Frustrated that I had replaced a perfectly good driver (at least now I have a spare), I decided the problem must be in the stepper motor. The erratic behavior (stuttering, random direction changes) seemed consistent with a burnt out phase. So it was back to eBay and ordering a new motor. (Mistake #2: jumping to conclusions without testing. Again.)

You can probably guess what happened when I got the new motor. Nope, it didn't fix the problem. So the problem couldn't be in the computer's parallel port, the breakout board or the drivers and now I had checked that the old motor actually worked fine when connected to the other axes. So what's the only thing left? The wiring. A multimeter revealed that one of the four wires in the stepper power cable was broken. After replacing the cable, the machine worked like new again.

In the end, the whole ordeal was cased by me thinking the wiring was the least likeliest part to fail and not testing that at the beginning. On the plus side, I now have an extra motor and an extra driver, so maybe I'll get around to building that 4th axis someday.

Sunday, November 27, 2011


I'm on roll. Just pushed my latest project, KQueryBrowser, to github. KQB is a database query tool for KDE that uses qt-webkit to format the query results nicely. And yes, I know the name is highly unoriginal and follows that annoying K<something> pattern, but at least it's descriptive.

The motivation for this yet another query tool was simply that I did not like any of the other query tools. The command like clients are nice, but awkward when browsing through very large tables. MySQL query browser was great, but was replaced by MySQL Workbench, which is way too cumbersome when I just want to run some SELECTs. Pgadmin suffers from the same problem. And most of the graphical tools use GTK, which makes them look ugly or (in the case of MySQL workbench) simply broken on KDE.

So here's KQB. Looks pretty on KDE, works with multiple databases and lets you get straight to writing queries.

Sunday, November 6, 2011


I just created a new repository on github for yet another hobby project I've been working on: piqs. It's a lightweight image gallery program with advanced tagging capabilities.

It's an experiment in alternative categorization; rather than sorting images into albums/folders, they are all shown in a single flat view, but that view can be filtered with tag queries. Of course, lots of gallery software have tagging capabilities nowadays, but piqs takes it a bit further. You can set up tag aliases and implication rules and something I don't think I've seen elsewhere: tag namespaces. For example, the tag string "[cat, orange], [dog, yellow], backyard" might be applied to a photo of an orange cat and a black dog taken in the backyard. The search string "cat, orange" will return all pictures with a cat and something orange, but the more specific "[cat, orange]" will return pictures of orange cats only. Further, boolean operators are supported: "cat, !dog" will return pictures with cats, but not dogs. "cat, (!dog|[dog,black])" will return pictures with cats and no dogs, unless the dog is black.

This sort of tagging only really starts to pay off once the image collection starts getting very large, so I've tried to design piqs to support huge galleries. So far, I've tried it with about 50000 untagged images and it hasn't choked yet. To help tag every image comprehensively, piqs can infer new tags based on a set of rules. E.g. the rules "cat --> mammal, carnivore", "mammal --> animal" will automatically add the tags "animal", "carnivore" and "mammal" to a picture tagged with "cat".

Saturday, April 23, 2011

Limit switches, part 2

In the previous post, I showed how I added limit switch inputs to my CNC driver box. Now its time to attach the actual switches to the machine.

Thursday, April 21, 2011

Limit switches, part 1

The CNC3040 machine doesn't come with limit switches and having already crashed the machine once I thought it was high time to add ones. The problem is that the driver box doesn't have inputs for the switches. My first idea was to build a passthrough box to break out the input pins, but peeking inside the case I found a nicer solution.

Wednesday, April 13, 2011

Griffin powermate + EMC2

I'm currently designing a physical control panel for use with EMC2 and for that I needed to learn how to use the HAL. HAL is EMC's hardware abstraction layer that provides a sort of virtual breadboard for connecting components, both hardware and software, together. One great thing about it is that it's really easy to write your own userspace HAL components in python. A short tutorial from EMC's documentation shows how. Also, Just Milling Around has a great tutorial on how to interface an Arduino with EMC using a python script.

As an exercise before getting started with my control panel, I decided to write a driver script for a piece of hardware I already have: A powermate jog wheel. My script creates two HAL pins: An output pin that can be connected to axis.N.jog-counts and a boolean input pin to turn the LED on and off.

The powermate HAL script is available here:

Friday, March 11, 2011

Improved image carving

JGCGen now has better support for image carving. Since the previous post, I've added two major features. The first is a roughing strategy for removing lots of material fast and in multiple passes so you can carve deeper. The second is the decoupling of image resolution from carving resolution. Stepover distance can now be smaller than a single pixel and jgcgen will interpolate the values in between. Another important change was a rather embarrassing bug fix: the tool shape profiles for flat and ballnose endmills were swapped! No wonder the previous test looked flatter than I expected...

Still on the TODO list: optimize rough path generation to minimize rapids and implement a waterline strategy.

Friday, March 4, 2011

Image carving

JGCGen now includes rudimentary support for heightmap carving. You can see the first test carving below. (source)

 Currently only a simple scanning style toolpath generation strategy is implemented, but different methods can be added easily.
Current limitations are:
  • No interpolation. The minimum stepover is image width or height divided by target width or height. This results in the striated look visible in the above image. A workaround is to use a higher resolution image.
  • Single pass only. This limits the depth of the image to the maximum depth your bit can handle.
My current plan is to add a strategy for a roughing pass that can be run with a bigger bit before running the finishing pass.

Tuesday, March 1, 2011

A BF interpreter in g-code

The unfortunately (but aptly) named brainf*ck is my favorite esoteric programming language. The whole language has only 8 commands, yet is Turing equivalent, meaning it has the same computational power as a Turing machine. As amazing as it sounds, this means any computable function can be computed with a BF program! A simple way to prove that a language is Turing complete is to use it to implement another which already has been proven Turing complete. Due to its simplicitly, BF lends itself well to this task.

So, here is a simple BF interpreter written in EMC's RS274 dialect:

o100 while [##<_pc> ne 0]
#1 = ##<_pc>
o101 if [#1 eq 1] (memory increment)
        ##<_p> = [##<_p> + 1]
o101 endif
o102 if [#1 eq 2] (memory decrement)
        ##<_p> = [##<_p> - 1]
o102 endif
o103 if [#1 eq 3] (pointer increment)
        #<_p> = [#<_p> + 1]
o103 endif
o104 if [#1 eq 4] (pointer decrement)
        #<_p> = [#<_p> - 1]
o104 endif
o105 if [#1 eq 5] (loop start)
        ##<_sp> = #<_pc>
        #<_sp> = [#<_sp> + 1]
o105 endif
o106 if [#1 eq 6] (loop end conditional)
        #<_sp> = [#<_sp> - 1]
        o1060 if [##<_p> ne 0]
                #<_pc> = [##<_sp>-1]
        o1060 endif
o106 endif
o107 if [#1 eq 7] (print value)
        #3 = ##<_p>
        (print, ASCII: #3)
o107 endif
g0 x1
#<_pc> = [#<_pc> + 1]
o100 endwhile
(print, PROGRAM END) 

This interpreter doesn't support the input command (but that isn't needed for Turing completeness anyway) and just prints out the output in numeric format. This is pretty boring, so I added a set of functions for carving out letters. See the complete source code.

Sunday, February 27, 2011

CNC tests: aluminum

Last time I tried how my CNC3040 machine deals with wood and plastic. Now it's time for some metal.

I tested on a piece of scrap aluminum, so unfortunately I have no idea of the alloy. The tool used was a 3mm 4-flute carbide endmill. Cutting depth was 0.4mm. For coolant I used Biltema brand "Multi-Spray".

The lower cut as seen in the picture was made with a feed rate of 50 mm/min and the one above it at 100mm/min. The faster cut looks cleaner.

I still need to do some more testing, but this machine does appear to be capable of light metalwork.

Generating G-Codes

As I said in my previous post, there is a dearth of CAM programs available for Linux, so I mostly have to write my G-Code by hand or combine output from various code generators. To make this task a little easier, I wrote a preprocessor with some code generation features too: JGCGen.

JGCGen is written in Java and uses Apache Velocity as its templating engine. This allows you to easily combine input files, write macros, generate code with loops, etc. Check out JGCGen's readme for a more comprehensive introduction to what it can do.

The g-code for the little name plate on the image to the right is, of course, generated with JGCGen. Yeah, it's not all that pretty and finished, but the code is only 24 lines long!

Addendum to the last post: You can cut plastic with a 2 flute endmill. Just keep the feed rate high enough to keep the chips from melting and clogging up the blades.

Friday, February 18, 2011

CNC tests: Wood and plastic

Today I did some tests on my CNCDIY 3040 router/mill to see how different speeds and feed rates affect the cut on various materials.
The materials tested were wood (oak), acrylic and polycarbonate.

I used a simple test pattern (G-code available here) with motions in different directions to help detect backlash and inaccuracies.

Saturday, February 12, 2011

Hobby CNC

For quite some time now, I had been wishing for a CNC router. On almost every project I did, whether that be woodworking or electronics, there was usually some part that made me think "if I had a CNC router, this would be easy;" but I couldn't justify spending thousands of euros on something (no matter how cool) I'd only be using for hobby work.
Recently, I found a manufacturer, CNCDIY, that makes affordable desktop CNC routers. They have (at the time of this writing) two very cheap models, the 2520 and the 3040, both under $1000. I decided to buy the 3040 as it has a slightly larger working area and has ball screws instead of trapezoids. According to the manufacturer, the 3040 can mill soft materials like wood, plastic and even aluminum. I would guess milling aluminum is very slow work on a machine like this compared to a "real" milling machine, but this machine should be just perfect for my needs. (Wood, acrylic, PCBs, possibly thin aluminum parts)

Monday, January 3, 2011

OS rants

Annoyances encountered today:
When I started up my desktop computer today (running Gentoo Linux) I noticed that my keyboard layout had, yet again, reset back to "us". The last time this happened was when the developers decided that the X configuration file was no longer a cool place to store configuration options and moved them out to HAL policy files. Took a bit of googling back then but I managed to get my keyboard working properly again easily enough.
So today, the HAL configuration was naturally the first place I looked. I remember that I had installed an update to xorg before shutting down my computer, so maybe some configuration key had been renamed or something. No amount of tweaking could restore the proper keymap. The configuration appeared fine in lshal, but X always loaded the default map. Finally, I found this. So apparently hal is now deprecated and udev is the way to go and settings are back in xorg.conf. Sigh. Progress I suppose.

Another problem. I tried to connect my work Windows 7 laptop to my home wireless network. After entering the details of my network, I was rewarded with the singularly unhelpful message "verkkoasetukset eivät ole tämän verkon edellytysten mukaiset", or something along those lines. (I accidentally selected the Finnish version when first starting up and haven't yet found the option to change it to English.) After some googling (good thing that wasn't my only computer!), it turned out this error (in my case) meant I had just selected the wrong encryption method (WPA vs. WPA2.)
But really? Can you make a less helpful error message? From the wording, I assumed I had to check some box somewhere to acknowledge that I'm allowed to connect to this network or something.