Laser cutter software

Dependencies:   EthernetNetIf mbed SDFileSystem

LaosMotion/LaosMotion.cpp

Committer:
pbrier
Date:
2011-08-11
Revision:
0:18ead85c200b

File content as of revision 0:18ead85c200b:

/**
 * LaosMotion.cpp
 * Motion Controll functions for Laos system
 *
 * Copyright (c) 2011 Peter Brier
 *
 *   This file is part of the LaOS project (see: http://wiki.protospace.nl/index.php/LaOS)
 *
 *   LaOS is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   LaOS is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with LaOS.  If not, see <http://www.gnu.org/licenses/>.
 *
 * 
 *
 */
#include "LaosMotion.h"

  
// status leds
extern DigitalOut led1,led2,led3,led4;

// Inputs;
DigitalIn xhome(p8);
DigitalIn yhome(p17);
DigitalIn zmin(p15);
DigitalIn zmax(p16);

// motors
DigitalOut enable(p7);
DigitalOut xdir(p23);
DigitalOut xstep(p24);
DigitalOut ydir(p25);
DigitalOut ystep(p26);
DigitalOut zdir(p27);
DigitalOut zstep(p28);

// laser

// DigitalOut laser(p22);       // O1: PWM (Yellow)
PwmOut pwm(p22);
DigitalOut laser_enable(p21);   // O2: enable laser
DigitalOut o3(p6);              // 03: NC
DigitalOut laser(p5);           // O4: LaserON (White)


// Analog in/out (cover sensor) + NC
DigitalIn cover(p19);

// globals
Ticker ticker;  // Timer
int ctr;

int step, prevcommand, command;
volatile int state, laseron;

// Besenham variables
int x0,y0,x1,y1,z0,z1;  // positions: 0=current, 1=new
int dx, sx; // step
int dy, sy;  // delta
int err, e2; // error


#define LASEROFF 1
#define LASERON 0

#define LOW_SPEED 400
#define HIGH_SPEED 90


/**
*** ticker: implement timer ticker, step if required
**/
void tick() 
{
  ctr++;
  // Control X,Y: line tracker
  switch ( state )
  {
    case 0: // idle (make sure laser is off)
      laser=LASEROFF;
      break;
    case 1: // init
      dx = abs(x1-x0);
      sx = x0<x1 ? 1 : -1;
      dy = abs(y1-y0);
      sy = y0<y1 ? 1 : -1; 
      err = (dx>dy ? dx : -dy)/2;
      xdir = sx > 0;
      ydir = sy > 0;
      if ( laseron )
        laser = LASERON;
      else
        laser = LASEROFF;
      state++;
      break;
    case 2: // moving
      if (x0==x1 && y0==y1) 
        state = 0;
      else
      {
        e2 = err;
        if (e2 >-dx) { err -= dy; x0 += sx; xstep = 1;}
        if (e2 < dy) { err += dx; y0 += sy; ystep = 1;}
      }
      break;
  }
  // Controll Z: tracking controller (independent of XY motion, not queued)
  if ( z1 != z0 ) 
  {
    zdir = z1 > z0;
    wait_us(5);
    zstep= 1;
    if ( z1 > z0 ) z0++;
    else z0--;
  }
  
  if ( xstep == 1 || ystep == 1 || zstep == 1 )
  {
    wait_us(5);
    xstep = ystep = zstep = 0;
  }
  
  // diagnostic info
  led1 = xdir;
  led2 = ydir;
  led3 = laseron;
  led4 = ctr & 4096;
} // ticker


/**
*** LaosMotion() Constructor
*** Make new motion object
**/
LaosMotion::LaosMotion()
{
  reset();
  laser=LASEROFF;
  pwm.period(0.0005);
  pwm = 0.5;
  //start.mode(PullUp);
  xhome.mode(PullUp);
  yhome.mode(PullUp);
  isHome = false;
  ticker.attach_us(&tick, HIGH_SPEED); // the address of the function to be attached (flip) and the interval (microseconds)
}

/**
***Destructor
**/
LaosMotion::~LaosMotion()
{

}

/**
*** reset()
*** reset the state
**/
void LaosMotion::reset()
{
  step = prevcommand = command = state = laseron = xstep = xdir = ystep = ydir = zstep = zdir = 0;
  laser=LASEROFF;
}



/**
*** ready()
*** ready to receive new commands 
**/
int LaosMotion::ready()
{
  return state == 0;
}

/**
*** write()
*** Write command to motion controller 
**/
void LaosMotion::write(int i)
{
 // printf("m:%d %d %d %d\n", state, step, i, command);
  if ( step == 0 )
  {
    prevcommand = command;
    command = i;
    step++;
  }
  else
  { 
     switch( command )
     {
          case 0: // move x,y (laser off)
          case 1: // line x,y (laser on)
            switch ( step )
            {
              case 1: x1 = i; break;
              case 2: 
                y1 = i;
                if ( prevcommand != command )
                 ticker.attach_us(&tick, (command ? LOW_SPEED : HIGH_SPEED)); // the address of the function to be attached (flip) and the interval (microseconds)
                laseron = (command == 1); state = 1; step = 0;
                break;
            } 
            break;
          case 2: // move z 
            switch(step)
            {
              case 1: z1 = i; step = 0; break;
            }
          case 3: // set t (1/v)
          switch(step)
          {
            case 1: ticker.attach_us(&tick, i); step=0; break;
          }
         case 4: // set x,y,z absolute
           switch ( step )
            {
              case 1: x0 = i; break;
              case 2: y0 = i; break;
              case 3: z0=z1 = i; step=0; break;
            }
         case 5: // nop
           step=0;
           break;
         default: // I do not understand: stop motion
            state = 0;
            step = 0;
          break;
    }
    if ( step ) step++;
  } 
}


/**
*** Return true if start button is pressed
**/
bool LaosMotion::isStart()
{
  return cover;
}


/**
*** Home the axis, stop when button is pressed
**/
void LaosMotion::home()
{
  int i=0;
  xdir = 0;
  ydir = 0;
  zdir = 0;
  led1 = 0;
  isHome = false;
  while ( 1 )
  {
    xstep = ystep = 0;
    wait(0.0001);
    xstep = xhome;
    ystep = yhome;
    wait(0.0001);
    
    led2 = !xhome;
    led3 = !yhome;
    led4 = ((i++) & 0x10000);
    if ( (!xhome) && (!yhome) ) return;
 //   if ( i > 2000 && !isStart()  ) return;  // debounce, and quit if key pressed again
  }
  isHome = true;
}