My Homemade CNC version 2 with USB Driven PIC16F877A Driver

This is the second version of my CNC machine that is capable of cutting plywood. (see version 1)

DSCF1099

DSCF1590

Skate bearings on L-Iron bars

333

Home made mechanical encoders. I later removed these and made the system open loop.

555

The controller software.

DSCF1589

PSU, Stepper Drivers and PIC

DSCF1588 DSCF1587 DSCF1586

Sketchup Models

1

X-Axis (bed)

2 3

Y-axis with Z-axis motor attached

4

Z-axis and router

Components

* 3A Stepper motors (280 oz-in I guess)
* Cheap TB6560 stepper drivers 24V-3A
* Thread bars and double nuts
* Skate bearings on rails
* 24V 10A SMPS
* CP210x USB-TTL module.
* Homemade Firmware (CCS-C) and driver program (VC++)
* PIC16F877A (more than enough)
* 1/4 inch Trim router + 2mm HSS end mill + V-bit

PIC Program (CCS-C)

core of the code

void main()
{
    int8 c;

    Setup();

    output_high(RED_LED);

    output_low(PIN_X_EN); // disable
    output_high(PIN_Y_EN);
    output_high(PIN_Z_EN);

    delay_ms(1000);
    output_low(RED_LED);
    output_low(GREEN_LED);

    while (TRUE)
    {
       output_high(LED_READY); // RX indicator
       c = my_getc();
       output_low(LED_READY); // RX indicator
       if (c == 0xff) // reset comm
       {
          gi_CmdCount = 0;
          gi_NextCmd = 0;
          continue;
       }
       else if (c == 0xfe) // end of transmission 
       {
          while (gi_CmdCount > 0)
          {
              output_high(LED_WORKING);
              DoNext();
              output_low(LED_WORKING);
          } 
      }

      if (gi_CmdCount >= MAX_CMDS)
      {
          SendNack(ERR_MSG_LIMIT);
          gi_CmdCount = 0;
          gi_NextCmd = 0;
          continue;
      }
      set_cmd(gi_CmdCount, c);
      gi_CmdCount++;
   }
}
//------------------------------------------------------------------------------
void ConfigureDevice(int8 iScale, int8 iActive, int8 iMaxActive)
{
   gi_Active = iActive;
   gi_Active *= 100;
   gi_MaxActive = iMaxActive;
   gi_MaxActive *= 100;
   gi_Scale = iScale;

   output_low(PIN_X_EN); // disable
   output_high(PIN_Y_EN);
   output_high(PIN_Z_EN);
}
//------------------------------------------------------------------------------
void UpdateDelay()
{
   if (gi_CurActive > gi_Active)
   {
      if (gi_CurActive > 3000) 
         gi_CurActive -= 1000;
      else if (gi_CurActive > 1000) 
        gi_CurActive -= 200;
      else
        gi_CurActive -= 50;
   }
}
//------------------------------------------------------------------------------
void Move(signed int iDir, int iAxis)
{
   // Y dir: Reversed to match hardware

   switch (iAxis)
   {
   case AXIS_X:
   {
     output_bit(PIN_X_DIR, iDir == FWD ? 0 : 1);
     output_high(PIN_X_CLK);
     output_high(LED_STEPPING);
     UpdateDelay();
     delay_us(gi_CurActive);
     output_low(PIN_X_CLK);
     output_low(LED_STEPPING);
     break;
   }
   case AXIS_Y:
   {
     output_bit(PIN_Y_DIR, iDir == FWD ? 0 : 1);
     output_high(PIN_Y_CLK);
     output_high(LED_STEPPING);
     UpdateDelay();
     delay_us(gi_CurActive);
     output_low(PIN_Y_CLK);
     output_low(LED_STEPPING);

     break;
  }
  case AXIS_Z:
  {
     output_bit(PIN_Z_DIR, iDir == FWD ? 1 : 0);
     output_high(PIN_Z_CLK);
     output_high(LED_STEPPING);
     UpdateDelay();
     delay_us(gi_CurActive);
     output_low(PIN_Z_CLK);
     output_low(LED_STEPPING);

     break;
  }
 }
}
//------------------------------------------------------------------------------
void RunManual()
{
 int16 i;

 output_low(LED_READY); 

 while (input_state(PIN_MANUAL) == 1)
 {
   if (input_state(PIN_Z_UP) == 1)
   {
      delay_ms(1000);
      gi_CurActive = gi_MaxActive;

      for (i = 0; i < 32000; i++)
         Move(FWD, AXIS_Z);
   }
   else if (input_state(PIN_Z_DOWN) == 1)
   {
       delay_ms(1000);
       gi_CurActive = gi_MaxActive;

       for (i = 0; i < 32000; i++)
           Move(BWD, AXIS_Z);
   }

   output_high(LED_BUSY);
   delay_ms(50);
   output_low(LED_BUSY);
   delay_ms(50);
 }

 delay_ms(1000);
}
//------------------------------------------------------------------------------
void DoNext()
{
   int8 cmd;
   sint16 a;
   int8 i;
   signed int m;
   signed int n;
   signed int k;

   cmd = get_cmd(gi_NextCmd);
   gi_NextCmd++;
   gi_CmdCount--;

   if (cmd == MOVE_XYZ)
   {
      if (gi_CmdCount < 2)
      {
         SendNack(ERR_ARGC);
         gi_CmdCount = 0;
         gi_NextCmd = 0;
         return;
      }
      m = get_cmd(gi_NextCmd) - 125; // distance
      gi_NextCmd++;
      gi_CmdCount--;
      n = get_cmd(gi_NextCmd) - 125; // axis
      gi_NextCmd++;
      gi_CmdCount--;
      gi_CurActive = gi_MaxActive;
      k = (m < 0 ? BWD : FWD);
      a = gi_Scale * abs(m);
     output_high(PIN_X_EN); // enable
     output_low(PIN_Y_EN);
     output_low(PIN_Z_EN);

     while (a > 0)
     {
        for (i = 0; i < 16; i++)
           Move(k, n);
        a--;

        /*if (input_state(PIN_MANUAL) == 1)
          {
              delay_ms(1000);
              RunManual();
              gi_CurActive = gi_MaxActive;
           }*/
      }

       output_low(PIN_X_EN); // disable
       output_high(PIN_Y_EN);
       output_high(PIN_Z_EN);

        gi_CurActive = gi_MaxActive;
    }
    else if (cmd == CONFIGURE_DEVICE)
    {
        if (gi_CmdCount < 3)
        {
             SendNack(ERR_ARGC);
             return;
        }
        m = get_cmd(gi_NextCmd); // scale
        gi_NextCmd++;
        gi_CmdCount--;
        k = get_cmd(gi_NextCmd); // active 
        gi_NextCmd++;
        gi_CmdCount--;

        i = get_cmd(gi_NextCmd); // max active 
        gi_NextCmd++;
        gi_CmdCount--;

        ConfigureDevice(m, k, i);
   }
   else
   {
      SendNack(ERR_NO_SUCH_CMD);
      gi_CmdCount = 0;
      gi_NextCmd = 0;
      return;
   }
   if (gi_CmdCount == 0) // All cmds executed 
   {
       gi_NextCmd = 0;
       SendAck();
   }
}