Mini Mill DRO

Done.

Wiring:

Uses iGaging Scales on the X and Y axis, Quad Encoder on the Z axis and infrared emitter/detector for the RPM.

Code X:

/******************************************************************/
/*                                                                */
/*                            MillDRO - X                         */
/*                                                                */
/*                            May 10, 2015                        */
/*                                                                */
/******************************************************************/

// iGaging Scale
// Red    3.3 Vcc
// White  Clock -> Scale W Pin 2
// Green  Data  <- Scale G Pin 3
// Black  Gnd

// Display 8 digit MAX7219                                 -a-
// VCC    R 5 Vcc                                         f   b 
// DIN    W MOSI Pin 11                                    -g-
// CS     Y SS   Pin 10                                   e   c 
// CLK    B SCK  Pin 13                                    -d-   p 
// GND    B Gnd                                          pgfe dcba   

// Zero switch 
// COM    B Gnd
// NO     Y Pin 9    

/******************************************************************/

#include <LedControl.h>

LedControl lc=LedControl(11,13,10,1);

/******************************************************************/

#define SCF   -3.906250 // Scale factor (1/2560*10000)

#define DLY   100       // Refresh period (100 ms)

#define SCC   2         // Scale clock (Pin 2)
#define SCD   3         // Scale data  (Pin 3)

#define SWZ   9         // Zero switch (Pin 9)

byte  DroIni;           // DRO init state
long  DroCnt;           // DRO raw counter  
long  DroOfs;           // DRO offset (zero)
long  DroMea;           // DRO measurement (inch *10000)
float DroKft;           // DRO scale factor


/******************************************************************/

void setup()
{
 IniSwz();                     // Init Zero switch
 IniScl();                     // Init Scale
 IniDsp();                     // Init Display
 IniClc();                     // Init Calc
}


void loop()
{
 ThrSwz();                     // Test Zero switch
 ThrScl();                     // Inquire Scale
 ThrClc();                     // Calc measure
 ThrDsp();                     // Display measure
 delay(DLY); 
}


/******************************************************************/


void IniClc(void)              // Init Calc
{
 DroIni=1;
 DroCnt=0;
 DroOfs=0;
 DroMea=0;
 DroKft=SCF; 
}


void ThrClc(void)              // Calc measure
{
 if(DroIni)
  {
   DroIni=0;
   DroOfs=DroCnt;
  }
 DroMea=FltLng((float)(DroCnt-DroOfs)*DroKft);
}


/******************************************************************/


void IniDsp(void)              // Init Display
{
 lc.shutdown(0,false);         // MAX7219 out of power-saving mode
 lc.setIntensity(0,8);         // Mediun value for brightness
 lc.clearDisplay(0);           // Clear display 
}

void ThrDsp(void)              // Display measure
{
 long v;
 int i,n,m;
 
 n=0;
 v=DroMea;
 if(v<0)
  {
   n=1;
   v*=-1;
  }
 for(i=0;i<8;i++)
  {
   m=v%10; 
   switch(i)
    {
     case 0:
            if(m>=5)
             lc.setDigit(0,i,5,false);
            else
             lc.setDigit(0,i,0,false);
            break;
     case 1:
     case 2:
     case 3:
            lc.setDigit(0,i,m,false);
            break;
     case 4:
            lc.setDigit(0,i,m,true);
            break;
     case 5:
     case 6:
     case 7:
            if(m)
             lc.setDigit(0,i,m,false);
            else
             {
              if(n)
               {
                n=0;
                lc.setChar(0,i,'-',false);
               }
              else
               lc.setChar(0,i,' ',false);
             }
            break;  
    }
   v/=10;   
  }
}


/******************************************************************/


void IniSwz(void)              // Init Zero switch
{
 pinMode(SWZ,INPUT_PULLUP);
}


void ThrSwz(void)              // Test Zero switch
{
 if(!digitalRead(SWZ))
  DroOfs=DroCnt;
}


/******************************************************************/


void IniScl(void)              // Init Scale
{
 digitalWrite(SCC,LOW);  
 pinMode(SCC,OUTPUT);     
 pinMode(SCD,INPUT);
}


void ThrScl(void)              // Inquire Scale
{
 int i;
 long v;
 
 v=0;
 for(i=0;i<20;i++)
  {
   ClkScl();
   if(BitScl())
    v|=0x80000000;
   v>>=1;
   v&=0x7FFFFFFF;
  }
 v>>=11;
 ClkScl();
 if(BitScl())
  v|=0xFFF00000;
 DroCnt=v;
}


void ClkScl(void)              // Clock Scale
{
 digitalWrite(SCC,HIGH); 
 delayMicroseconds(20); 
 digitalWrite(SCC,LOW); 
 delayMicroseconds(100); 
}


int BitScl(void)              // Get Scale bit
{
 int i;
 int h,l;
 
 h=l=0;
 for(i=0;i<5;i++)
  {
   if(digitalRead(SCD))
    h++;
   else
    l++;
   delayMicroseconds(SCD); 
  }
 if(h>l)
  return(1);
 return(0);
}


/******************************************************************/


long FltLng(float v)
{
 return((v<0)?(long)(v-0.5):(long)(v+0.5)); 
}

Code Y:

/******************************************************************/
/*                                                                */
/*                            MillDRO - Y                         */
/*                                                                */
/*                            May 10, 2015                        */
/*                                                                */
/******************************************************************/

// iGaging Scale
// Red    3.3 Vcc
// White  Clock -> Scale W Pin 2
// Green  Data  <- Scale G Pin 3
// Black  Gnd

// Display 8 digit MAX7219                                 -a-
// VCC    R 5 Vcc                                         f   b 
// DIN    W MOSI Pin 11                                    -g-
// CS     Y SS   Pin 10                                   e   c 
// CLK    B SCK  Pin 13                                    -d-   p 
// GND    B Gnd                                          pgfe dcba   

// Zero switch 
// COM    B Gnd
// NO     Y Pin 9    

/******************************************************************/

#include <LedControl.h>

LedControl lc=LedControl(11,13,10,1);

/******************************************************************/

#define SCF   3.906250  // Scale factor (1/2560*10000)

#define DLY   100       // Refresh period (100 ms)

#define SCC   2         // Scale clock (Pin 2)
#define SCD   3         // Scale data  (Pin 3)

#define SWZ   9         // Zero switch (Pin 9)

byte  DroIni;           // DRO init state
long  DroCnt;           // DRO raw counter  
long  DroOfs;           // DRO offset (zero)
long  DroMea;           // DRO measurement (inch *10000)
float DroKft;           // DRO scale factor


/******************************************************************/

void setup()
{
 IniSwz();                     // Init Zero switch
 IniScl();                     // Init Scale
 IniDsp();                     // Init Display
 IniClc();                     // Init Calc
}


void loop()
{
 ThrSwz();                     // Test Zero switch
 ThrScl();                     // Inquire Scale
 ThrClc();                     // Calc measure
 ThrDsp();                     // Display measure
 delay(DLY); 
}


/******************************************************************/


void IniClc(void)              // Init Calc
{
 DroIni=1;
 DroCnt=0;
 DroOfs=0;
 DroMea=0;
 DroKft=SCF; 
}


void ThrClc(void)              // Calc measure
{
 if(DroIni)
  {
   DroIni=0;
   DroOfs=DroCnt;
  }
 DroMea=FltLng((float)(DroCnt-DroOfs)*DroKft);
}


/******************************************************************/


void IniDsp(void)              // Init Display
{
 lc.shutdown(0,false);         // MAX7219 out of power-saving mode
 lc.setIntensity(0,8);         // Mediun value for brightness
 lc.clearDisplay(0);           // Clear display 
}

void ThrDsp(void)              // Display measure
{
 long v;
 int i,n,m;
 
 n=0;
 v=DroMea;
 if(v<0)
  {
   n=1;
   v*=-1;
  }
 for(i=0;i<8;i++)
  {
   m=v%10; 
   switch(i)
    {
     case 0:
            if(m>=5)
             lc.setDigit(0,i,5,false);
            else
             lc.setDigit(0,i,0,false);
            break;
     case 1:
     case 2:
     case 3:
            lc.setDigit(0,i,m,false);
            break;
     case 4:
            lc.setDigit(0,i,m,true);
            break;
     case 5:
     case 6:
     case 7:
            if(m)
             lc.setDigit(0,i,m,false);
            else
             {
              if(n)
               {
                n=0;
                lc.setChar(0,i,'-',false);
               }
              else
               lc.setChar(0,i,' ',false);
             }
            break;  
    }
   v/=10;   
  }
}


/******************************************************************/


void IniSwz(void)              // Init Zero switch
{
 pinMode(SWZ,INPUT_PULLUP);
}


void ThrSwz(void)              // Test Zero switch
{
 if(!digitalRead(SWZ))
  DroOfs=DroCnt;
}


/******************************************************************/


void IniScl(void)              // Init Scale
{
 digitalWrite(SCC,LOW);  
 pinMode(SCC,OUTPUT);     
 pinMode(SCD,INPUT);
}


void ThrScl(void)              // Inquire Scale
{
 int i;
 long v;
 
 v=0;
 for(i=0;i<20;i++)
  {
   ClkScl();
   if(BitScl())
    v|=0x80000000;
   v>>=1;
   v&=0x7FFFFFFF;
  }
 v>>=11;
 ClkScl();
 if(BitScl())
  v|=0xFFF00000;
 DroCnt=v;
}


void ClkScl(void)              // Clock Scale
{
 digitalWrite(SCC,HIGH); 
 delayMicroseconds(20); 
 digitalWrite(SCC,LOW); 
 delayMicroseconds(100); 
}


int BitScl(void)              // Get Scale bit
{
 int i;
 int h,l;
 
 h=l=0;
 for(i=0;i<5;i++)
  {
   if(digitalRead(SCD))
    h++;
   else
    l++;
   delayMicroseconds(SCD); 
  }
 if(h>l)
  return(1);
 return(0);
}


/******************************************************************/


long FltLng(float v)
{
 return((v<0)?(long)(v-0.5):(long)(v+0.5)); 
}

Code Z:

/******************************************************************/
/*                                                                */
/*                            MillDRO - Z                         */
/*                                                                */
/*                            May 10, 2015                        */
/*                                                                */
/******************************************************************/

// Quad Encoder 600 ppr LPA3806
// Red    5 Vcc
// White  Chanel A Pin 2 (Int 1)
// Green  Chanel B Pin 3 (Int 2)
// Black  Gnd

// Display 8 digit MAX7219                                 -a-
// VCC    R 5 Vcc                                         f   b 
// DIN    W MOSI Pin 11                                    -g-
// CS     Y SS   Pin 10                                   e   c 
// CLK    B SCK  Pin 13                                    -d-   p 
// GND    B Gnd                                          pgfe dcba   

// Zero switch 
// COM    B Gnd
// NO     Y Pin 9    

/******************************************************************/

#include <LedControl.h>

LedControl lc=LedControl(11,13,10,1);

/******************************************************************/

#define SCF   4.000000  // Encoder factor (1/((600*4)/(12*0.08))*10000)

#define DLY   100       // Refresh period (100 ms)

#define QCA   2         // Encoder Chanel A (Pin 2)
#define QCB   3         // Encoder Chanel B (Pin 3)

#define QIA   0         // Encoder Chanel A (Int 1)
#define QIB   1         // Encoder Chanel B (Int 2)

#define SWZ   9         // Zero switch (Pin 9)

long  DroCnt;           // DRO raw counter  
long  DroOfs;           // DRO offset (zero)
long  DroMea;           // DRO measurement (inch *10000)
float DroKft;           // DRO scale factor


/******************************************************************/


void setup()
{
 IniSwz();                     // Init Zero switch
 IniEnc();                     // Init Encoder
 IniDsp();                     // Init Display
 IniClc();                     // Init Calc
}


void loop()
{
 ThrSwz();                     // Test Zero switch
 ThrClc();                     // Calc measure
 ThrDsp();                     // Display measure
 delay(DLY); 
}


/******************************************************************/


void IniClc(void)              // Init Calc
{
 DroCnt=0;
 DroOfs=0;
 DroMea=0;
 DroKft=SCF; 
}


void ThrClc(void)              // Calc measure
{
 DroMea=FltLng((float)(DroCnt-DroOfs)*DroKft);
}


/******************************************************************/


void IniDsp(void)              // Init Display
{
 lc.shutdown(0,false);         // MAX7219 out of power-saving mode
 lc.setIntensity(0,8);         // Mediun value for brightness
 lc.clearDisplay(0);           // Clear display 
}

void ThrDsp(void)              // Display measure
{
 long v;
 int i,n,m;
 
 n=0;
 v=DroMea;
 if(v<0)
  {
   n=1;
   v*=-1;
  }
 for(i=0;i<8;i++)
  {
   m=v%10; 
   switch(i)
    {
     case 0:
            if(m>=5)
             lc.setDigit(0,i,5,false);
            else
             lc.setDigit(0,i,0,false);
            break;
     case 1:
     case 2:
     case 3:
            lc.setDigit(0,i,m,false);
            break;
     case 4:
            lc.setDigit(0,i,m,true);
            break;
     case 5:
     case 6:
     case 7:
            if(m)
             lc.setDigit(0,i,m,false);
            else
             {
              if(n)
               {
                n=0;
                lc.setChar(0,i,'-',false);
               }
              else
               lc.setChar(0,i,' ',false);
             }
            break;  
    }
   v/=10;   
  }
}


/******************************************************************/


void IniSwz(void)              // Init Zero switch
{
 pinMode(SWZ,INPUT_PULLUP);
}


void ThrSwz(void)              // Test Zero switch
{
 if(!digitalRead(SWZ))
  DroOfs=DroCnt;
}


/******************************************************************/


void IniEnc(void)              // Init Encoder
{
 pinMode(QCA,INPUT_PULLUP);
 pinMode(QCB,INPUT_PULLUP);
 attachInterrupt(QIA,QenChAInt,CHANGE); 
 attachInterrupt(QIB,QenChBInt,CHANGE); 
}


void QenChAInt(void)                        // Interruption chanel A
{
 if(PIND&4)
  {                 // Chanel A High
   if(PIND&8)
    DroCnt++;       // Chanel B High (increase)
   else
    DroCnt--;       // Chanel B Low  (decrease)
  }
 else
  {                 // Chanel A Low
   if(PIND&8)
    DroCnt--;       // Chanel B High (decrease)
   else
    DroCnt++;       // Chanel B Low  (increase)
  }
}


void QenChBInt(void)                        // Interruption chanel B
{
 if(PIND&8)
  {                 // Chanel B High
   if(PIND&4)
    DroCnt--;       // Chanel A High (decrease)
   else
    DroCnt++;       // Chanel A Low  (increase)
  }
 else
  {                 // Chanel B Low
   if(PIND&4)
    DroCnt++;       // Chanel A High (increase)
   else
    DroCnt--;       // Chanel A Low  (decrease)
  }
}


/******************************************************************/


long FltLng(float v)
{
 return((v<0)?(long)(v-0.5):(long)(v+0.5)); 
}

Code R:

/******************************************************************/
/*                                                                */
/*                            MillDRO - R                         */
/*                                                                */
/*                            May 10, 2015                        */
/*                                                                */
/******************************************************************/

// IR Sensor TCRT5000
// Red    5 Vcc
// White  Aout 
// Green  Dout Pin 3 (Int 2)
// Black  Gnd

// Display 4 digit SAA1064 
// 3/8    None                                            -a-
// 5/8    None                                           f   b
// VCC    R 5 Vcc                                         -g-
// ADR    B Gnd (Read Addr 0x70 / Write Addr 0x71)       e   c 
// SDA    W Pin A4 SDA                                    -d-   p
// SCL    Y Pin A5 SCL                                  
// GND    B Gnd                                         pgfe dcba 

/******************************************************************/

#include <Wire.h>

#define DSP   0x38        // Display Addr (0x70>>1)

byte DspDig[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

/******************************************************************/

#define MXL   0xffffffff  // Maximum timer count (us)

#define RCF   60000000    // RPM factor 

#define RMX   6000        // Maximum RPM time us (debounce) 10000 RPM
#define RMN   6000000     // Minimum RPM time us (zero) 10 RPM

#define DLY   100         // Refresh period (500 ms)

#define SNS   3           // Sensor digital out (Pin 3)

#define SIT   1           // Sensor (Int 2)

unsigned long  RpmTmr;    // RPM timer (microseconds)
unsigned long  RpmCnt;    // RPM counter (microsecond)
unsigned long  RpmFac;    // RPM factor

int  RpmMea;              // RPM measurement
int  RpmAvr[10];          // RPM measurement average

/******************************************************************/

void setup()
{
 IniSns();                     // Init Sensor
 IniDsp();                     // Init Display
 ClrDsp();                     // Clear Display
 IniClc();                     // Init Calc
}


void loop()
{
 ThrClz();                     // Test RPM
 ThrClc();                     // Calc RPM
 ThrDsp();                     // Display RPM
 delay(DLY); 
}


/******************************************************************/


void IniClc(void)              // Init Calc
{
 byte i;
 
 RpmTmr=micros();
 RpmCnt=0;
 RpmMea=0;
 RpmFac=RCF; 
 for(i=0;i<10;i++)
  RpmAvr[i]=0;
}


void ThrClz(void)              // Test rpm zero
{
 unsigned long t,d;
 
 t=micros();
 if(t>RpmTmr)
  d=t-RpmTmr;
 else
  d=MXL-t+RpmTmr;
 if(d>RMN)                     // Test RPM counter zero
  RpmCnt=0;
}


void ThrClc(void)              // Calc rpm measure
{
 byte i,j;
 int r,p,s;

 if(RpmCnt>0)
  {
   r=RpmFac/RpmCnt;
   s=RpmMea*10;
   if((r<s)||(s==0))
    {
     s=0;
     for(i=0,j=1;i<9;i++,j++)
      {
       p=RpmAvr[j];
       RpmAvr[i]=p;
       s+=p;
      }
     RpmAvr[i]=r;
     s+=r;
     s/=10;
     RpmMea=s;
    }
  }
 else
  RpmMea=0;
}


/******************************************************************/


void IniDsp(void)              // Init Display
{
 Wire.begin();                 // Start up I2C bus
 delay(500);
 Wire.beginTransmission(DSP);
 Wire.write(B00000000);        // Instruction byte. Zero: the next byte is the control byte
 Wire.write(B00100111);        // Control byte (dynamic mode, digits 1+3 on, digits 2+4 on, 6 mA current
 Wire.endTransmission();
}

void ClrDsp(void)              // Clear display
{
 Wire.beginTransmission(DSP);
 Wire.write(B00000001);        // Instruction byte. One: first digit is 1 (right side)
 Wire.write(B00000000);        // Digit 1 (Right)
 Wire.write(B00000000);        // Digit 2
 Wire.write(B00000000);        // Digit 3
 Wire.write(B00000000);        // Digit 4 (Left)
 Wire.endTransmission();
}


void ThrDsp(void)              // Display measure
{
 int i;
 long v;
 byte d[4];
 
 v=RpmMea;
 for(i=0;i<4;d[i]=v%10,v/=10,i++);
 Wire.beginTransmission(DSP);
 Wire.write(B00000001);        // Instruction byte. One: first digit is 1 (right side)
 Wire.write(DspDig[d[3]]);     // Digit 4 (left)
 Wire.write(DspDig[d[2]]);     // Digit 3 
 Wire.write(DspDig[d[1]]);     // Digit 2
 Wire.write(DspDig[d[0]]);     // Digit 1 (right)
 Wire.endTransmission();
}


/******************************************************************/


void IniSns(void)              // Init Sensor
{
 pinMode(SNS,INPUT_PULLUP);
 attachInterrupt(SIT,SnsInt,FALLING); 
}


void SnsInt(void)              // Sensor Interruption 
{
 unsigned long t,d;
 
 t=micros();
 if(t>RpmTmr)
  d=t-RpmTmr;
 else
  d=MXL-t+RpmTmr;
 if(d>RMX)                     // Debounce
  RpmCnt=d;
 RpmTmr=t;
}

nice photo :wink:

"Arduino QuadCore"

Awesome! 8) :grin: