Introduction: Ardudro

About: Recent graduate from CMU, now working at Northrop Grumman. Mostly inactive at this point, but still around occasionally.

The aduino is one of the most popular microcontrollers, and has been used in almost any imaginable scenario.  Its one of the easiest ways to make software with physical interactions.  It has done to microcontrollers what 3D printers did to mechanical manufacturing, and is, in fact, commonly used to control such printers.  But what about makers/instructablers who need part that can't be made on a printer, or made of unprintable materials?  This is where mills hold the high seat, but mills are expensive, and unless they're CNC, counting revolutions and converting units to make accurate parts can be a pain, and commercial DRO systems cost hundreds of dollars.  Enter Ardudro, a simple and cheap system that allows for easy milling with high accuracy and repeatibility.     

Step 1: What Is Ardudro?

The ardudro, or ARDUino Digital ReadOut is a simple system which displays the exact position of a mill, and will soon be able to do basic milling functions (such as pockets, profiles, circles, position drilling, etc), all while using parts you probably already have, or that can be bought at a certain "telecommunications hut".  All you need is:
Small TV: any kind, any size you want, must have an NTSC/PAL input, or the little yellow plug for video.  This is what will display everything, so match the size to your mill.  Most thrift stores will have an old portable TV at some time or another, I got mine for about $5.   
Arduino: any flavor with an atmega328, 32u4, or more powerful.  I used an UNO.
1k ohm resistor: any wattage
330-470 ohm resistor: also any wattage
two momentary switches/buttons: optional, but used for zeroing X and Y axes. 
RCA jack: one of those yellow-red-white plugs for a TV, or a willingness to solder directly to the TVs rca jack. 
rotary encoder: this is probably the only part you dont already have.  These are avaliable at almost all electronics stores/sites except radioshack.  A 32 cycle encoder is avaliable here: http://www.sciplus.com/p/QUESTEK-POSITIONSENSING-ENCODER_50792
this determines the accuracy of the readout.  Divide one by the revolutions per inch on your mill axes times four times the number of encoder cycles per revolution.  This is the distance of each "step", which is the increment (and therefore accuracy) of the readout.  In my case, it was 1/(20*4*32)=1/2560=0.000390625.  This will give me about 1/1000 accuracy, which should be more than accurate enough for anyone who would use this instead of a commercial DRO system. 

Something to connect your encoders to the mill's axes: I used rubber stopper that I cut a slot in.  

Step 2: Electron Divergence.

The electronics for this are fairly simple.  Connect the encoders to power however they need to be (mine were infrared, and thus needed positive and ground connections to function), then, connect the A and B channels of one encoder to pins two and seven of the arduino, and A and B of the other to three and six.  Which channel goes where does not matter, that can be fixed with code. 
Connect the two switches/buttons between 10 and 11, and ground, again, doesn't matter which one goes where.  

Finially, connect the 470 ohm resistor to pin8 and the 1K to pin 9.  Connect the ends of both to the center of the rca jack, and the arduino's ground to the outside of it.    

Now, to the "fun part".  Code.   

Step 3: Pre-Code. Yay.

The code for this is fairly simple, but requires two libraries.  The first is the encoder library, avaliable here http://www.pjrc.com/teensy/td_libs_Encoder.html  (download is at the top of the page, two lines below the title), the second is the TVout library, avaliable here  http://code.google.com/p/arduino-tvout/downloads/list  (I believe I used R5.91). 

Step 4: My Code. Even More Yay.

This is the current version of the code (rev2), and it only supports x and y reset buttons, and little else (still working on milling functions). 
Just copy and paste into arduino and it should work if you already have the encoder and tv libraries. 

//Ardudro program, revision 2



//#define ENCODER_OPTIMIZE_INTERRUPTS
//haven't tried using the above line yet, may make it faster, but may not. 
#include <Encoder.h>
#include <TVout.h>
int xminus = 0;
int yminus = 0;
Encoder myEnc(2, 7);//flip "myEnc" and "Ecy" if the X and Y axes are backwards
Encoder Ecy(3, 6);
float anaval = 0;
float value01 = 0;
float val = 1000;
float value;
float value10;
float value100;
int out;
int r = 0;
float pos = 0;
int rd = 4;
long np = 0;
float incr = 0.000390625; //1/2560, this number may change for your setup.  Make sure to use a decimal, not a fraction. 
int onx = 12;
int negx = 0;
long npy = 0;
int ty = 0;
TVout TV;
const int buttonx = 11;//flip these two (x and y, or the numbers) if the buttons are off. 
const int buttony = 10;
unsigned char x,y;
char i = 48;
int ic = 6;
void setup()  {
  pinMode(buttonx,INPUT);
  pinMode(buttony,INPUT);
  digitalWrite(buttonx,HIGH);
  digitalWrite(buttony,HIGH);
  x=0;
  y=0;
  TV.begin(_NTSC,110,30);
}

void loop() {
if(digitalRead(buttonx) == 0){ //this doesn't need to be read immediately, so we'll use the loop
//instead of an interrupt.  Plus, the encoders use the other interrupts.
  myEnc.write(0);
}
if(digitalRead(buttony) == 0){ //same here. 
  Ecy.write(0);
}

  np = myEnc.read();
// np = np*-1; //uncomment if the X axis is flipped
   delay(1);
   ty = 0;
   TV.print_char(onx,ty,'X');
if (val != np) {
   if (np < 0){
     val = -1 * np;
     negx = 1;
   }else{
    val = np;
    negx = 0;
   }
}
disp();
np = Ecy.read();
// np = np*-1;//uncomment if the Y axis is flipped
   delay(1);
   ty = 10;
   TV.print_char(onx,ty,'Y');
if (val != np) {
   if (np < 0){
     val = -1 * np;
     negx = 1;
   }else{
    val = np;
    negx = 0;
   }
}
disp();
}


void stringer(){
value01 = val;
value = val / 10;
value10 = val / 100;
value100 = val / 1000;
value = int(value);
value10 = int(value10);
value100 = int(value100);
value01 = int(value01);
value01 = value01 - (value * 10);
value = value - (value10 * 10);
value10 = value10 - (value100 * 10);
}

void disp(){
  val = val * incr;
val = int(val * 1000);
  stringer();
  if (negx == 1){
    TV.print_char(onx-ic,ty,'-');
  } else {
      TV.print_char(onx-ic,ty,' ');
  }
         TV.print_char(onx+ic,ty,char(value100)+48);
    TV.print_char(onx+(ic*2),ty,char(value10)+48);
    TV.print_char(onx+(ic*3),ty,char(value)+48);
    TV.print_char(onx+(ic*4),ty,char(value01)+48);

}

Step 5: What Does It Do?

The code should be pretty simple, all it does is read the encoder and display the number right?  Not quite.  The data must be read to the display as either a char or a string, so the float that represents the distance will not work.  The "stringer" void separates the number into 1s, 10s, 100s and 1000s place, and the "disp" void displays them in series, as well as the X and Y, and negative sign, if need be. 

Step 6: Assembly

Upload the code, then plug it into the encoders and TV.  If you see:
X0.000
Y0.000

displayed in very large letters, its working.
Press the two buttons, one should clear X, the other Y. 

Box up/encose the project however you wish.  Because of the variance in system setup, every enclosure will be different.  
Now, attach the encoders to the mill's shafts, and turn it on again. 

Move the mill in the X and Y and try rezeroing the axes, and remember where it was backward (were X and Y flipped? did it display negative when it should be positive?)

Both are very easy to adjust in the code.  To flip X and Y, go to the 5th and 6th lines of code (not comments at the top) flip, as per the comments, "myEnc" and "Ecy".  These are the definitions of each, so flipping these will effectively flip it everywhere else in the code. 
Re-upload, and check everything else.  The buttons can be flipped three lines above setup, and the +/- of the axes can be flipped just after each encoder read int the loop (just uncomment the commented code to flip) 

If all that works, then that's it!  You just made a $40 or less system equivalent to those costing many times more.  Dont forget to look for code updates soon, or to vote for me in the arduino contest.   

Step 7: More Coming Soon*

For now, you're done!  I will update the codes for more functionality, but I felt that it would be good to get this out there now, and see if anyone would even use it.  Tell me what you think or want to see added, and don't forget to vote for me in the arduino contest!




*By "soon" I mean the same timeframe as your neighbor uses when he promises to return your weedwacker and battery charger for your hedge trimmer, specifically, around the time the sun goes out, or shortly thereafter.

Weekend Projects Contest

Participated in the
Weekend Projects Contest

Arduino Contest

Participated in the
Arduino Contest