Saturday, October 27, 2012


Driving a Floppy Drive Brushless Motor

I took apart an old floppy drive a while back and in it I found a really nice looking motor. At first I though it just looked nice but I would never get it to run. I thought about throwing it away but then thought "It's cute maybe I will do something with it one day." and threw it in a box with a bunch of other junk that I might do something with one day.

Well, the day has come for the little brushless motor.

The first thing I did was look around and see what was on the Internet (I could become an instant expert). Google has lots of hits on "floppy drive motor" and "brushless motor" and they were not really what I was looking for. I had discarded the circuit board (probably in the box of junk some where) and would need to drive the motor directly with my own driver circuit. Finally, I ran across a link at eLABS called "Driving a three-phase brushless DC motor with Arduino - Part 1. Theory" witch led to "Brushless DC (BLDC) motor with Arduino – Part 2. Circuit and Software". They are wonderfully written and really got me and the motor on my way. Most of what I am writing is how I got the motor to turn a little bit. eLABZ's write-up is more complete and has a lot more on how and why the motors work.

This is just a little project to get the motor to turn. It is not going to power a quadrocopter or a motorcycle but it should get the motor turning without much effort. It might even be a learning experience, it certainly was for me.

The motor

First thing I did was try to find out what each pin on the motor was for. There are 15 pins and to date I have only identified three of them. The first three (see figure #) are to the coils. The last two pins (14 and 15) got to the big sensor that I think is a hall effect sensor (I have not hooked this up yet). That leaves 10 pins unaccounted for but I think they are to more sensors to get position and/or speed information.


Pins Function Nice picture
1 to coil set #1
2 to coil set #2
3 to coil set #3
4 - 13 ???
14 Vin for big hall effect sensor ?
15 output for big hall effect sensor ?


When I started, I expected to see two pins for each set of coils. Instead I found only one pin to each set of coils (there are 12 coils, three sets of four). One end of each set of coils goes to it's pin. The other end is tied to the other two sets of coils. Reading a little about brushless motors I found out why.

So, there are 6 or 7 ohms of resistance between any two pins because the path between the pins goes through two sets of coils. This is sort of nice because I will only need 1/2 h-bridge to drive each set of coils. Each pin will be set either positive (+5V) or negative (to ground). You can see where the coils are tied together two pins to the right of the glob of solder that goes to pin #1.

I got out my Ardiuno and set up a little circuit wrote a little program and watch what happened.

The circuit

First I hooked everything together. I had some L293D quadruple high-current half H-bridge drivers. I could have used discrete transistors but these were sitting there and are all ready to go. I only needed three of the four half h-bridges. The only other components I used were two 1kOhm resistors. I put it all together on a breadboard and wired it to the Arduino.

  1. Hook up three Arduino pins (9,10,11) to three of the "In" pins on the L293D (2, 9, 12). 
  2.  Put 1000k resistors (Brown, Black, Red) between the two "Enable" pins on the L293D (1, 11) and the 5V supply on the Arduino.  . 
  3.  The L293D pins 4, 5, 12 and 13 get grounded.
  4.  I also hooked the Arduino 5V supply to the Vs and Vss pins on the L293D
  5. The L293D pins 3, 6, and 14 got to the motor pins 1, 2, and 3.
  6. Pins 10 and 11 on the L293D are not used (it is the half H-bridge that it not used).

The breadboard and schematic were both made using software from Fritzing. It is really easy to use and I think the results are nice (despite my lack of skills in this area).

The three coils can be hooked up how ever you like. If you get it wrong it might turn backwards.  This is because there are only six ways to hook them up. Three of the ways are ABC, BCA,  and CAB. The other three ways are just a mirror of the first three, CBA, ACB, and BAC. So, if you get the motor turning and you would like for it to turn the other was you could just switch any two of the three wires.
 




The Program

 I wrote a really simple program to drive the motor. It is not meant to be used in any sort of application. It was written to make the motor turn and it works...sort of. Below is a listing for the program. you should be able to copy it directly and nake it work. There are comments in the program (parts with "//" in front of it) that might make reading it easer.

// values for PMW
int levels[48] = {127,  144,  160,  176,  191,  205,  217,  228,  237,  245,  250,  253,  255,  253,  250,  245,
                  237,  228,  217,  205,  191,  176,  160,  144,  127,  110,   94,   78,   63,   49,   37,   26,
                   17,    9,    4,    1,    0,    1,    4,    9,   17,   26,   37,   49,   63,   78,   94,  110};

// These are the pins used to drive the motor.
int pinA = 9;
int pinB = 10;
int pinC = 11;

int step = 0;               // Keeps track of what pulse width to use 
unsigned long lastTime = 0; // the time in micros since last step
int period = 5000;          // set motor speed by defining time between steps

void setup()
{
  // Set pins as digital outputs
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);

  // Set all the pins LOW
  digitalWrite(pinA, LOW);
  digitalWrite(pinB, LOW);
  digitalWrite(pinC, LOW);
}

void loop()
{
  // Check if it is time for the next step
  if ((micros() - lastTime) >= period)
  {
    // Next three lines send pulse width value for this step.
    analogWrite(pinA, levels[step]);
    analogWrite(pinB, levels[(step + 16) % 48]);
    analogWrite(pinC, levels[(step + 32) % 48]);

    // Add one to set (% 48 rolls step back to 0 after it fits 47)
    step = (step + 1) % 48;

    // make note of current time
    lastTime = micros();

    // ramps up the speed
    if (period > 500)
    {
      period -= 1; // make speed faster (the period between steps smalled)
    }
  }
}  

It is a very simple program meant to get the motor to turn. It starts out slow (and not very smooth) and get faster (ans finally runs smoothly).
The top part of the program defines
 variables These variables are:

levels:
This is the pulse width values (arduino PWM). It is a look-up table and it means the Arduino can just look the value up in this table instead of calculating it each time (these calculations take time, I just did it in another program so the Arduino would not have to.
pinX:
These three define the pin numbers for the Arduino's output.
step:
This keeps track of where to look in the look-up table.
lastTime:
The last time the step was changed.
period:
How long to wait after the lastTime to step again.
Then comes the setup function for the Arduino. It gets everything ready for the main loop. The first there lines set the pinX pins as outputs and then there are thee lines that sets them "LOW" or makes them 0 voltage.

Then then comes the main loop function. This should not be confused with "a" loop (such as a "for" loop or a "while" loop). It is "the" loop and everything that happens in this loop keeps happening until you unplug the Arduino.

The first line of the main loop checks if enough time has lapsed to move to the next step. It checks with an "if" statement. It uses micros(), a clock that keeps track of how long the Arduino has been on in microseconds. Subtracting lastTime from the time returned with micros() gives the time since the last step. If it is longer than the period then it takes the next step.

The next step (the next three non commented lines) is to write the PWM from the lookup table to the output pins with analogWrite. The first argument (in parentheses) is the pin to write to. The second argument is the value found in the look up table. pinA gets the value of the variable step (the arduino starts counting at 0). When step = 0 the value is 127. pinB gets the value at step + 16. The "% 48" uses the Arduino's modulo operator. It makes sure that the value of step + 16 is not  bigger than 47 because there are only 48 values in the look up table(remember the Arduino starts counting at 0. 0 to 47 is 48 values). pinC gets the value at step + 32.

The modulo operator might seem a little confusing but it really makes things easer. Imagine having to write into the program something to deal with step + 16 being bigger that 47. The fact that the Arduino starts counting at 0 might be a little confusing but ... that is the way it is. Computers are like that.

Then the program increments the step by on.

Then it makes note of the current time using micros().

Then there is another if statement that checks if the motor is spinning at the maximum speed yet (the shortest period). If not it subtracts one from period until the period is 500 (that is 500 microseconds between steps).

And that is it. Upload the program to the arduino and watch it run. There is still work to be done to make it run smoother and faster but it turns. 

I tried the same technique on a little hard drive motor and it ran really well (sorry no video yet).

There are a few things I would like to change. I think it is under powered and would run better (especially at lower speeds) if I used a power source other than the 5V from the Arduino. I would like to add some speed control to it, maybe a potentiometer, to make it a little more fun. Of course it would be nice to run in both directions with the same program (I just need to have it step backwards through the PWM levels). The coils on the motor look nice and I think I will cut windows in the spindle so they can be seen at the motor turns.

That is all for now. Go and have fun.

Tuesday, August 21, 2012

Gary's 2nd DIY CNC Touch Probe.

I made a little, fairly simple, touch probe for my little CNC a few months ago. I have been meaning to get back to it to make some improvements, maybe building a little better version, but one thing after another came up and I never got around to it. Finally, a couple days ago I started thinking about a new probe. What I came up with is different than the first but it works well. It still has some weaknesses but one of these days I will try again.

The earlier probe had some problems. For one, sometimes after making contact with the sample it would stick open. While stuck open it triggered EMC2 at the start of the next probe, and the next. This meant that it skipped over much of the area and left stripes in the data.

Also, the old probe took a fair bit of pressure to trigger. The sharp point on the end of the probe combined with the need for the probe to press a little hard on the surface to trigger meant it could mare softer surfaces. This was not really a problem for what I was using it for but it made scanning delicate things impossible.

Leaf Switch


With these two drawbacks of the old design and wanting to get something build quickly and inexpensively I started work. First, I looked in a bunch of old electronic junk I had laying around for some sort of switch. I found a small leaf switch that looked just about right. It is made up of a springy piece of metal with a contact over a ridged piece of metal with a contact. The two contacts are normally touching and very little pressure is needed to break contact.





Leaf switch, little nail, broken bit and lots of hot glue.


To make the probe, I just used a little hot glue to glue a small nail to the springy piece part of the switch. Then I with some more hot glue I glued that all to a broken 1/4" router bit (I have a couple of those floating around unfortunately). I soldered a cable to the contacts on the switch (it takes two conductors, one ground and one for +5V). Then I hooked it up to the motor controller (see my old project on how to do this).





I made a change to the g code for EMC2 to use. It is all well and good that the old code scans a rectangle but I want to scan a dime. The dime is round and using a square pattern takes to much time. So, I broke out the trig I have learned over the years and got the CNC to scan in a circle. Again, it may not be the best example of gcode but it works for me.

<gcode>
G94 f15       ; feed inches/min

#1 = 0.00        ; X min
#2 = 0.00        ; Y min
#3 = 0.740        ; X max 0.99
#4 = 0.740       ; Y max 0.99
#5 = 0.04          ; Z max
#6 =-0.025         ; Z min
#7 = 0.002         ; X step
#8 = 0.002         ; Y step

#12 = #2           ; Y position
#13 = [#3 / 2]     ; hypotenuse

G0 Z #5
(PROBEOPEN probeResults.txt)
#12 = [-1 * #13]
O1 Do
  #14 = [#13 * cos[asin[ #12 / #13]]] ; end x
  #15 = [-1 * #14] ; start x
  O2 Do
    G0 X #15 Y #12
    G38.3 Z #6
    G0 Z #5
    #15 = [#15 + #7]
  O2 While [#15 le #14]
  #12 = [#12 + #8]
  O4 If [#12 / #13 le 1]
    #15 = [#13 * cos[asin[ #12 / #13]]] ; start x
    #14 = [-1 * #15] ; end x
    O3 Do
      G0 X #15 Y #12
      G38.3 Z #6
      G0 Z #5
      #15 = [#15 - #7]
    O3 While [#15 ge #14]
  O4 EndIf
  #12 = [#12 + #8]
O1 While [#12 le #13]
(PROBECLOSE)

G0 Z #5
G0 X #1 Y #2
M2
</gcode>


Results:
It works.
I scanned a dime and it took all night for the above code to get the job done. The blue in the image of the dime are places where the probe did not contact anything before the end of the probe run. The grey is, of course the dime. The red is where it was triggered at the start of the probe run. I think a bug got stuck under the probe (I was sleeping when it happened).

There are still issues to be dealt with. If you look close the edge of the coin came out pretty jagged. This seams to be because nail I was using as the probe stylus is to flexible. Well, it will give me something to work on.

Thursday, June 28, 2012

Simple CNC Switch Plate Cover

This post has been updated. To see the updates look for the items in red labeled "Update".

  I have been playing with a little CNC machine for about 2 years now and it has been fun. Still, as much fun as it has been, I think it would be nice if it started to pay for itself. So, I started to think about all the things I might make with a small (about 6.5"x6.5" cutting area) that I could sell. There are lots of ideas but after some considerations I have started making some light switch covers. After a little searching and a bunch of measuring I have a sort of basic template that I can start making covers with.

    Before I settled on light switch covers I ran through many ideas. There are a few things I needed to keep in mind. I have a Zen Toolworks 7x7 inch CNC. (http://www.zentoolworks.com). So, what ever I make needs to have parts that will fit on the table. Also, I would like to start selling some things on Etsy pretty soon so nothing too complicated. A clock kit with lots of gears was one early idea. I have been working on this for a while and it will have to be a future story. I am really fascinated by the notion of a mechanical computer, something like a mechanical Arduino. This is also for the future. These things might be a little involved to be my first jump into making a little money with a CNC.


After some more thought I hit on switchplate covers. They should be pretty straight forward and I think there is a lot of room for customization. The plates in the hardware stores are pretty plain (even the fancy ones). After making a few plain plates there aught to be able to move into more involved designed. So, I got out a couple covers and started measuring.





(Update (Sept 26, 2012): The distance between the screw holes should read "2.375"))
The outside of the plates that I measured were 2 3/4"x4 1/5". The standard screws are #6x32 ovel head screws and would normally use a hole about 0.1440" but I just drilled 1/8" holes. They are a little tight but it is wood and does not present a problem and it holes the screw in place. The holes are 2 13/32" apart (that is center to center). I counter sunk the holes making the to diameter 1/4" and 3/32" deep. The hole for the toggle switch is 7/16" x 15/16". I am making the plates from 1/4 plywood and it might be a tiny bit thick but it works fine. I route out the back of the plate 1/8" deep and leave about 1/4" around the edge.



DXF file:
    coming soon (I need to find a place to host the file)
    (Update (Sept 26, 2012):   basicSwitchPlate.dxf. 
      This is a file in my github repository. To download the file look down the page and find the file called "basicSwitchPlate.dxf". Right click on the file and choose "Save link as ...". If you left click on the file the dxf will open in your browser and you will see the text file that makes up a dxf file. The distance in the dxf file between the screw holes has changed in the dxf file. It should be 2.375" .)

Gcode file:
      Before you use the gcode take a look at it. It is what I am using but your setup is likely different. I used a 1/8" bit for the front of the plate. The bit I used for the back is a little less than 1/2". I think it is undersized to cut groves for 1/2" plywood to fit into.

     I added little tabs so the plate does not break out of the plywood panel while it is cutting. There are four around the outside and two in the little  piece that gets cut out for the toggle switch. Also, I call the subroutine to cut the screw holes twice. I find this helps make the holes smoother.

BasicFront.ngc
#1 = 0         ; Set project vars and material vars
#1  =  15.0;    feed-rate
#2  =  0.25;    up
#3  =  0.0;    down
#4  =  1;    tool number for using the cutter diameter compensation
#5  =  0.12500;    cutter diameter for initial move
#6  =  #3;    to keep track of current cutter depth
#7  = -0.25000;    material thickness
#8  =  0.04100;    cutter step - depth

; Modal settings
G17      ;XY plane
G20      ;inch mode
G40      ;cancel diameter compensation
G49      ;cancel length offset
G54      ;coordinate system 1
G80      ;cancel motion
G90 F#1      ;non-incremental motion
G94      ;feed/minute mode

; counter sunk hole
O500 Sub
  #11 = [#11 - [#5 / 2]] ; subtract cutter diameter
  #12 = [#12 - [#5 / 2]] ; subtract cutter diameter
  #14 =  0.01000 ; step for depth
  #16 =  [[#11 - #12] / [-1 * #13 / #14]]
  G90 F#1  
  G0 X [#9 + [#11 / 2]] Y [#10 + 0.0000]
  O501 Do
    G1 X [#9 + [#11 / 2]] Y [#10 + 0.0000]
    G1 Z #6
    G3 X [#9 + [#11 / 2]] Y [#10 + 0.0000] I [-1 * [#11 / 2]] J 0.0000
    #6 = [#6 - #14]
    #11 = [#11 - #16]
  O501 While [#6 ge #13]
  G0 Z #2;    move tool up to safe heights
  #6 = #3;    reset working depth

  G0 X  #9 Y  #10
  G1 Z  #3 F#1
  G1 Z  #7 F5.0
  G1 Z  #2 F#1
O500 Endsub

; Initial position
G0 Z #2 ;      
G0 X  0.00000 Y  0.00000
G0 X  1.00000 Y  1.00000

; Screw holes
; counter sink hole
#9  =  1.37500 ; center X
#10 =  3.45629 ; center y
#11 =  0.25000 ; max diameter
#12 =  0.13000 ; min diameter
#13 = -0.09000; depth
O500 Call [#1] [#2] [#3] [#4] [#5] [#6] [#7] [#8] [#9] [#10] [#11] [#12] [#13]
O500 Call [#1] [#2] [#3] [#4] [#5] [#6] [#7] [#8] [#9] [#10] [#11] [#12] [#13]

; second hole
; counter sink hole
#9  =  1.37500 ; center X
#10 =  1.04687 ; center y
#11 =  0.25000 ; max diameter
#12 =  0.13000 ; min diameter
#13 = -0.09000; depth
O500 Call [#1] [#2] [#3] [#4] [#5] [#6] [#7] [#8] [#9] [#10] [#11] [#12] [#13]
O500 Call [#1] [#2] [#3] [#4] [#5] [#6] [#7] [#8] [#9] [#10] [#11] [#12] [#13]


; Switch hole
G0 X  [1.15625 + #5] Y  [2.25000 + #5]
G41 D#4
G1 X  1.15625 Y  2.25000

O200 Do
  G1 Z  #6
  G1 X  1.15625 Y  1.78125

  O201 If [#6 ge #7 + 0.0625]  ; tab    G1 X  1.59375 Y  1.78125
  O201 Else
    G1 Z  [#7 + 0.06250]
     G1 X  1.59375 Y  1.78125
    G1 Z  #6
  O201 EndIf
  G1 X  1.59375 Y  2.71875
  O202 If [#6 ge #7 + 0.0625]
  ; tab
      G1 X  1.15625 Y  2.71875
  O202 Else
    G1 Z  [#7 + 0.06250]
       G1 X  1.15625 Y  2.71875
    G1 Z  #6
  O202 EndIf
  G1 X  1.15625 Y  2.25000
  #6 = [#6 - #8]
O200 While [#6 ge #7]
G0 Z #2
G40
#6 = #3;  reset working depth

; Outside
G0 X  [1.37500 - #5] Y  [0.00000 - #5]
G42 D#4
G1 X  1.37500 Y  0.00000

O201 Do
  G1 Z  #6
  G1 X  2.68749 Y  0.00000
  G3 X  2.75000 Y  0.06250 I  0.00000 J  0.06250
  O202 If [#6 ge #7 + 0.0625]
    G1 X  2.74500 Y  3.76284
  ; tab
  O202 Else
    G1 Z  [#7 + 0.06250]
    G1 X  2.74500 Y  0.37500
    G1 Z  #6
    G1 X  2.74500 Y  3.38784
    G1 Z  [#7 + 0.06250]
    G1 X  2.74500 Y  3.76284
    G1 Z  #6
  O202 EndIf

  G1 X  3.28364 Y  3.76284
  G3 X  3.32971 Y  3.86757 I  0.00000 J  0.06250
  G1 X  1.41739 Y  5.95374
  G3 X  1.33261 Y  5.95374 I -0.04239 J -0.04620
  G1 X -0.57972 Y  3.86757
  G3 X -0.53365 Y  3.76284 I  0.04607 J -0.04223
  G1 X  0.00000 Y  3.76284

  O203 If [#6 ge #7 + 0.0625]
  ; tab
    G1 X  0.00000 Y  0.06250
  O203 Else
    G1 Z  [#7 + 0.06250]
    G1 X  0.00000 Y  3.38784
    G1 Z  #6
    G1 X  0.00000 Y  0.37500
    G1 Z  [#7 + 0.06250]
    G1 X  0.00000 Y  0.06250
    G1 Z  #6
  O203 EndIf
  G3 X  0.06250 Y  0.00000 I  0.06250 J  0.00000
  G1 X  1.37500 Y  0.00000
  #6 = [#6 - #8]
O201 While [#6 ge #7]
G0 Z #2
G40
#6 = #3;  reset working depth

; Go back to Initial position
G0 Z #2 ;            move cutter up
G0 X  0.00000 Y  0.00000 ;    move cutter up
; End File
M2

BasicBack.ngc
#1 = 0        ; Set project vars and material vars
#1  =  17;    feed-rate
#2  =  0.5;    up
#3  =  0.0;    down
#4  =  4;    tool number for using the cutter diameter compensation
#5  =  0.46875;    cutter diameter for initial move
#6  =  #3;    to keep track of current cutter depth
#7  = -0.12500;    material thickness
#8  =  0.0625;    cutter step - depth


; Modal settings
G17      ;XY plane
G20      ;inch mode
G40      ;cancel diameter compensation
G49      ;cancel length offset
G54      ;coordinate system 1
G80      ;cancel motion
G90 F#1      ;non-incremental motion
G94      ;feed/minute mode


; Initial position
G0 Z #2 ;       
G0 X  0.00000 Y  0.00000
G0 X  1.00000 Y  1.00000


; Inside Faceing
G0 X  0.56260 Y  0.56260
#9 = 0.56260

O200 Do
  G1 Z #6 F#1
  O201 Do
    G1 X  #9 Y  0.56260
    G1 X  #9 Y  3.93739
    #9 = [#9 + 0.23625]
    G1 X  #9 Y  3.93739
    G1 X  #9 Y  0.56260
    #9 = [#9 + 0.23625]
  O201 While [#9 le 2.43740]
  G1 Z #2
  G0 X  0.56260 Y  0.56260
  #9 =  0.56260
  #6 = [#6 - #8]
O200 While [#6 ge #7]

G0 Z #2
#6 = #3;  reset working depth


; Inside Edge
G0 X  [0.18750 + #5] Y [0.18750 + #5]
G42 D#4
G0 X  0.18750 Y  0.18750
G1 Z  #7
G1 X  0.18750 Y  4.31249
G1 X  2.56249 Y  4.31249
G1 X  2.56249 Y  0.18750
G1 X  0.18750 Y  0.18750
G1 X  0.18750 Y  1.00000
G0 Z #2
G40


; Go back to Initial position
G0 Z #2 ;            move cutter up
G0 X  0.00000 Y  0.00000 ;    move cutter up
; End File
M2

     This seams to work ok for me. I have put a few up for sale on Etsy. Hopefully I will soon be making some more and slightly more elaborate plates.

Saturday, April 7, 2012

Gary's DIY CNC Touch Probe

 DIY CNC Touch probe

  I got a little CNC machine a couple years ago and it has been fun to have around. I have cut out all sorts of little things. There is a mount for a Dremmel, a Kite Areal Photography (KAP images) rig, a bunch of wooden gears, some clocks, and other little stuff. Most recently, I have been working on a CNC touch probe. Originally the probe was to help me level the CNC table. It took a little effort and learning but now it is up and running (sort of) and I had to try it out. It is not perfect and there are things I am planning to do to it but I think I have an OK start.

  A touch probe for a CNC is a pretty simple device. Basically the touch probe is used with the CNC to measure distances of things mounted on the work platform. It mounts on the CNC where the cutter usually is and is moved in one direction, in the Z axis (up and down) for instance, until it touches something and it stops. After it stops it can record the position of the end of the probe to a file. If this procedure is repeated many time you end up with a "point cloud", a map of the hight of the object being measured.  The point cloud can be used for many different things. It could be used to create a G-code program to copy the thing that has been measured. It could be used to make a picture or map and I am hoping it can be used to help level my CNC table.

I started out looking at some examples of homemade touch probes. There are a few pretty good ones on the Internet.
http://www.indoor.flyer.co.uk/probe.htm
http://www.brusselsprout.org/CNC/1P-Probe/
http://fadedbits.com/2011/02/touchprobe/
http://www.vinland.com/touch-probe.html
http://www.cnczone.com/forums/digitizing_laser_digitizing/22837-cheap_home_made_touch_probe.html

Expired patent for the Renishaw touch probe.
Google Patents

Some of the sites made things look a little intimidating but I was not looking for super accuracy. This is more of a proof of concept than anything else. So, I got started.

The design

Disclaimer:
    I am not a super a super engineer or anything. I just threw together the design below to see if I could get anything to work. So, if you try any of this be careful, don't poke out an eye or break anything.

Warning:
    The drawings you are about to see are not the prettiest you have ever seen.


  The probe is very simple. It is just a switch that is normally closed and when the tip of the probe touches something it opens the circuit (breaking the connection) and sends a signal to the controlling software to stop probing. The probe tip is a little piece of brass rod sticking out the bottom of the body of the probe. The switch is three pieces of brass rod attached to the top of the probe (held together with non-conduction material, this case it is wood) resting on six screws. The screws are wired together and positioned so that the "switch" is closed normally and lifts up off the screws when it hits something. 

I cut the body out of 1/4" plywood. The body design is simple. The top and bottom are just round discs with some holes, the side is made out of rings, and the top of the probe are made from discs with groves for the brass switch rods and a hole in the center for the probe. I used a few 1/8" dowel pins to keep everything straight and a cut off 1/4" bolt as a shank to attach the probe to the CNC spindle. I wrote a few g-code files to cut everything out and got started.











While the wood parts were being cut out I cut four pieces of 3/16" brass rod. One for the probe and three for the switches. I also looked around and found six screws with round heads for the rod to rest on. The heads are round so when the switch is closed the rod can make contact with the screws and when the probe lifts up just a little bit it breaks contact.
Assembling things was easy. I glued the three brass rods into the discs cut out for the top of the probe. Stuck the rod for the probe into the little disc. I glued a spring to the top of the probe disc to hold the probe down on the screws. Next the switch screws were put into the holes I cut for them in the bottom piece. Then I glued the side rings onto the bottom and screwed the top on. The 1/4" bolt went in a hole in the center of the top. When I cut the bolt left a little of the threads at the bottom screw into the wood and part sticking out was smooth. This would fit into the 1/4" collet of the CNC spindle.

Then I soldered some wire to the bottom of the switch screws. One piece of wire between each set of screws and a couple pieces from a couple screws to the controller. The wire I used to hook up to the controller is long enough to reach from the CNC to the controller. I checked with an ohm meter that all the switches were closed (and adjusted the screws up and down to make them close).



 Set Up

    I am have a Zen Toolworks 7"x7" CNC put together from a kit. It is a little small but has worked out well and been fun.
  http://www.zentoolworks.com/product_info.php?products_id=74
   
    The stepper motor controller is a Geckodrive G540 4 axis controller. I only have 3 axis but can dream of a forth.
  http://www.geckodrive.com/g540-digital-axis-motor-control-p-39.html

    As for software to run the CNC I am using EMC2 Ver. 2.4.3. It is free, works well, and runs on Linux. The last item is important as I do not have any computers that run on windows.
   http://www.linuxcnc.org/

    For a spindle I am using a Bosch Colt router with a 1/4" collet.

    To set up the probe I first put put the probe in the router. The shank of the 1/4" bolt is a little small for the collet. Next time I will find something that fits better (I also want a better mount for the router, but that is another story). Please note that with the probe installed in the router it would be a mistake to turn the router on. Spinning at 16,000 RPM, the probe with a 2 foot piece of wire hanging off would, at the very least, make a mess of the project.

    Next I hooked up the wires out of the probe to the G540 controller. One goes to pin 1 (corresponds to pin 10 on the parallel port) and the other to ground (pin 12 on the G540)



    To set up EMC2 I just used the stepper configuration program and chose to modify the set up I already had to run the machine without the probe. On the second screen of the set up wizard, "Parallel Port Set Up" I set pin 10 to be "Probe In". (At first I had pin 10 set to "Digital In", this is a mistake.) That was all the set up there was.

 

 

G Code

    The sample program that came with EMC2 did not work for me. I don't know why. I did not try to figure it out. I just wrote another little gcode program that probed every position on a grid. It is not fancy but it worked for me.

A few notes about the g code.

I set the minimum Z (the deepest I wanted the probe to go) to a little above the table. I did not want the probe to miss something and keep going down.
   
G38.3 is the code to I used to probe (see the EMC2 users manual). You could also use G38.2. The difference is that G38.3 does not stop for probing errors like reaching the final probe depth and not hitting anything. G38.2 stops the program and reports an error and I did not want this to happen.

I used "G38.3 Z #6" to set the probe to probing. The "G38.3" tells the machine to use the probe. The "Z" tells the machine to probe in the Z direction (you can also probe sideways and other directions, to find the edge of a work piece). The "#6" (where #6 is set at the top of the program to equal 0.05") is as far down as I want the probe to go before stopping.

I added comments in the code, they should help understand the code. I tried to make everything readable but, well, it is not english.

I see not that I forgot to add a line to the top of the g code to tell it to run in inches. I forgot a few things but everything worked ok for me.

; probe.ngc
G94 f2       ; feed inchs/min

; Set up the grid that I want to scan.
; The XY min and max values set up the XY size of the grid
: The Z min max values define the start of the probing run 
; and the end of the run if the probe touches nothing 
#1 = 0            ; X min
#2 = 0            ; Y min
#3 = 0.7     ; X max
#4 = 0.6    ; Y max
#5 = 0.12      ; Z max
#6 = 0.05       ; Z min
#7 = 0.01       ; X step
#8 = 0.01       ; Y step


#11 = #1   ; X position
#12 = #2   ; Y position

; move the probe tip up so it does not run into anything
G0 Z #5      

; open a file to record the probed results in
(PROBEOPEN probeResults.txt)


O1 Do            ; O1 is a loop for X grid values (rows)
  #11 = 0        ; set X to 0 at the start of each Y column

  O2 Do            ; O2 is a loop for the Y grid values (columns)
    G0 X #11 Y #12    ; move to new grid position
    G38.3 Z #6        ; probe down to the minimum Z value
    G0 Z #5        ; raise the probe tip so it does not run into anything
    #11 = [#11 + #7]    ; add the X step to X, the next grid point.
  O2 While [#11 le #3]    ; keep this up until reaching the maximum X value
  #12 = [#12 + #8]    ; done with this row (Xs) move to next column (Ys)
O1 While [#12 le #4]    ; keep this up intil reaching the last column (max Y)

(PROBECLOSE)        ; close the probe file full of points

G0 Z #5            ; raise the probe tip so it does not run into anything
G0 X #1 Y #2        ; move to the start point
M2            ; end the g code

Results
    It turned out a better than I had feared it might and worse than I had hoped. I was not super careful in cutting parts out and putting them together. In fact I was rather cavalier about the whole thing. So, I was happy with what I got and confident I can do better next time.

    I built this thing to check that the CNC work surface is parallel to the X and Y axis of motion. If these axis are not parallel then the machine will cut deeper on one side of the work piece than the other and spoil what might otherwise be a nice piece of work. First though, I decided to test it by scanning a US Quarter. I glued a quarter to a piece of plywood, stuck it on the CNC table and got to scanning.



First scan    For my very first attempt I set the scanning are to 1"x1" and the XY step between grid points to 0.005". This was way to slow for my tastes. So, I changed the scanning area to 0.7"x0.6" and scanned the center section of the quarter. One problem that I had was the probe would touch the quarter, open the switch, and then not close. This meant the switch was open at the start of the next grid point and would be triggered at the highest point. At times like this I reached in tap the probe and the switch would close. When this happened the machine recorded the top of the probe run (0.12", Z max in the gcode). That is what all the white stripes were are in the image.

Epilogue


    Like I said above, I am happy with the way things turned out. The next one will turn out better. I will be more careful with the construction and I believe that will help with the precision of the device. I also have an idea about how to make sure the switch closes after it is triggered. I think I will use three springs, one above each switch, to push the rod back down instead of the one spring in the center.

I hope this write up is helpful to some one. Let me know what you think. Take care and have a good time.
Gary

Update :(Oct 16, 2012: A while back I made another touch probe. It is much simpler and a description can be found on the blog (here).