Laser Electronics: Difference between revisions

From Hacklab.TO Public Wiki
Jump to navigation Jump to search
(remove unimplemented power control mod.... irrelevent)
(→‎Code: Updated source to assumed code)
Line 48: Line 48:


=== Code ===
=== Code ===
When we replaced the motor controllers back in 2016; we moved the step generation logic off the PIC, and replaced it with a single "MOTOR_EN" output instead.
The original code changes have not been found, so the following is assumed but unvalidated.


<pre>
<pre>
/*
/*
  * Laser Engraver Controller - ver. 1.0
  * Laser Engraver Controller - ver. 1.1a
  *
  *
  * Written by: Andrew Kilpatrick
  * Written by: Andrew Kilpatrick
  * Copyright: 2009
  * Copyright: 2009, 2016
  *
  *
  * Runs on PIC16F877A
  * Runs on PIC16F877A
Line 62: Line 66:
  *  - parallel port or other type of bit-bang connection to PC
  *  - parallel port or other type of bit-bang connection to PC
  *  - E-stop and system run control support (amp enable, charge pump, etc.)
  *  - E-stop and system run control support (amp enable, charge pump, etc.)
*  - controls 3 stepper motors (X, Y, Z)
  *  - controls laser PWM control
  *  - controls laser PWM control
  *
  *
  * Hardware I/O:
  * Hardware I/O:
  *  - RA0 - laser power bit 0 - input - active high
  *  - RA0   - laser power bit 0       - input - active high
  *  - RA1 - laser power bit 1 - input - active high
  *  - RA1   - laser power bit 1       - input - active high
  *  - RA2 - laser power bit 2 - input - active high
  *  - RA2   - laser power bit 2       - input - active high
  *  - RA3 - laser power bit 3 - input - active high
  *  - RA3   - laser power bit 3       - input - active high
  *  - RA4 - laser defeat - input - active high
  *  - RA4   - laser defeat           - input - active high
*
*  - RB0 - E stop loop - input - 0 = run, 1 = stop
*  - RB1 - Z dir - input - 0 = back, 1 = forward
*  - RB2 - Y dir - input - 0 = back, 1 = forward
*  - RB3 - X dir - input - 0 = back, 1 = forward
*  - RB4 - laser activate - input - 0 = off, 1 = on
*  - RB5 - Z step - input - rising edge - move one step
*  - RB6 - Y step - input - rising edge - move one step
*  - RB7 - X step - input - rising edge - move one step
  *
  *
  *  - RC0 - amp enable LED - output - 0 = off, 1 = on
  *  - RB0    - E stop loop            - input - 0 = run, 1 = stop
  *  - RC1 - laser LED - output - 0 = off, 1 = on
  *  - RB3    - motor_enable            - output
  *  - RC2 - laser PWM - output - 0 = off, 1 = on
  *  - RB4    - laser activate        - input - 0 = off, 1 = on
*  - RC4 - Z motor phase A - output
*  - RC5 - Z motor phase B - output
* - RC6 - Z motor phase C - output
*  - RC7 - Z motor phase D - output
  *
  *
  *  - RD0 - X motor phase A - output
  *  - RC0    - amp enable LED        - output - 0 = off, 1 = on
*  - RD1 - X motor phase B - output
  *  - RC1    - laser LED            - output - 0 = off, 1 = on
  *  - RD2 - X motor phase C - output
  *  - RC2    - laser PWM            - output - 0 = off, 1 = on
- RD3 - X motor phase D - output
  *  - RD4 - Y motor phase A - output
- RD5 - Y motor phase B - output
*  - RD6 - Y motor phase C - output
*  - RD7 - Y motor phase D - output
  *
  *
  *  - RE0 - E stop output - output - 0 = stop, 1 = run
  *  - RE0   - E stop output           - output - 0 = stop, 1 = run
  *  - RE1 - amp enable input - input - 0 = disable, 1 = enable
  *  - RE1   - amp enable input       - input - 0 = disable, 1 = enable
  *  - RE2 - charge pump input - input - high pulses to charge
  *  - RE2   - charge pump input       - input - high pulses to charge
  *
  *
  */
  */
Line 116: Line 101:
#define LASER_DEFEAT_IN porta.4
#define LASER_DEFEAT_IN porta.4
#define E_STOP_IN portb.0
#define E_STOP_IN portb.0
#define X_DIR_IN portb.3
#define MOTOR_EN portb.3
#define Y_DIR_IN portb.2
#define Z_DIR_IN portb.1
#define X_STEP_IN portb.7
#define Y_STEP_IN portb.6
#define Z_STEP_IN portb.5
#define LASER_IN portb.4
#define LASER_IN portb.4
#define AMP_ENABLE_IN porte.1
#define AMP_ENABLE_IN porte.1
Line 133: Line 113:
// laser setting
// laser setting
#define LASER_TICKLE 0x01
#define LASER_TICKLE 0x01
// motor step size - 1 = half-step, 2 = full step
#define X_STEP_SIZE 1
#define Y_STEP_SIZE 1
#define Z_STEP_SIZE 1


// run state machine
// run state machine
Line 146: Line 121:


// globals
// globals
unsigned char x_phase; // the X motor step phase
unsigned char run;               // 1 = normal, 0 = stopped
unsigned char y_phase; // the Y motor step phase
unsigned char charge_pump;       // 0 = stopped, >0 = run
unsigned char z_phase; // the Z motor step phase
unsigned char run; // 1 = normal, 0 = stopped
unsigned char charge_pump; // 0 = stopped, >0 = run
unsigned char old_ch_pump;
unsigned char old_ch_pump;
unsigned char laser_init; // 1 = laser initialized, 0 = not initialized
unsigned char laser_init;       // 1 = laser initialized, 0 = not initialized
unsigned char laser_power; // laser power level
unsigned char laser_power;       // laser power level
unsigned char laser_on; // 1 = laser on, 0 = laser off
unsigned char laser_on;           // 1 = laser on, 0 = laser off
unsigned char flash; // temp flasher variable
unsigned char flash;           // temp flasher variable
unsigned char x_step; // temp x step state
unsigned char y_step; // temp y step state
unsigned char z_step; // temp z step state


// function prototypes
// function prototypes
Line 165: Line 134:
// main loop
// main loop
void main() {
void main() {
// set up IO
    // set up IO
porta = 0x00;
    porta = 0x00;
trisa = 0xff;  // inputs
    trisa = 0xff;  // inputs
adcon1 = 0x06;  // all digital pins
    adcon1 = 0x06;  // all digital pins
 
portb = 0x00;
    portb = 0x00;
trisb = 0xff;  // inputs
    trisb = 0xF7;  // inputs except for MOTOR_EN
option_reg.NOT_RBPU = 0;  // weak pullups
    option_reg.NOT_RBPU = 0;  // weak pullups
 
portc = 0x00;
    portc = 0x00;
trisc = 0x00;  // outputs
    trisc = 0x00;  // outputs
AMP_ENABLE_LED = 0;
    AMP_ENABLE_LED = 0;
LASER_ON_LED = 0;
    LASER_ON_LED = 0;
ccpr1l = 0x00;
    ccpr1l = 0x00;
ccp1con = 0x0c;  // PWM mode
    ccp1con = 0x0c;  // PWM mode
t2con = 0x05;  // prescaler 4, timer on
    t2con = 0x05;  // prescaler 4, timer on
 
portd = 0x00;
    trise.PSPMODE = 0;  // no data port
trisd = 0x00;  // outputs
 
trise.PSPMODE = 0;  // no data port
    porte = 0x00;
    trise &= 0xfe;  // RE0 = output, RE1-2 = input
porte = 0x00;
    E_STOP_OUT = 1;  // no E stop
trise &= 0xfe;  // RE0 = output, RE1-2 = input  
E_STOP_OUT = 1;  // no E stop


t1con = 0x21;  // 1:4 prescaler, internal clock, timer on
    t1con = 0x21;  // 1:4 prescaler, internal clock, timer on


// reset temp vars
    // reset temp vars
x_phase = 0;
    run = 0;
y_phase = 0;
    laser_init = 0;
z_phase = 0;
    laser_on = 0;
run = 0;
    flash = 0;
laser_init = 0;
    run_state = STATE_IDLE;
laser_on = 0;
    charge_pump = 0;
flash = 0;
    old_ch_pump = 0;
x_step = 0;
y_step = 0;
z_step = 0;
run_state = STATE_IDLE;
charge_pump = 0;
old_ch_pump = 0;


// bootup light dance
    // bootup light dance
AMP_ENABLE_LED = 0;
    AMP_ENABLE_LED = 0;
LASER_ON_LED = 1;
    LASER_ON_LED = 1;
delay_ms(250);
    delay_ms(250);
delay_ms(250);
    delay_ms(250);
AMP_ENABLE_LED = 1;
    AMP_ENABLE_LED = 1;
LASER_ON_LED = 0;
    LASER_ON_LED = 0;
delay_ms(250);
    delay_ms(250);
delay_ms(250);
    delay_ms(250);
AMP_ENABLE_LED = 0;
    AMP_ENABLE_LED = 0;


// loop
    // loop
while(1) {
    while(1) {
clear_wdt();
        clear_wdt();
     
// do stuff every 50ms
        // do stuff every 50ms
if(pir1.TMR1IF) {
        if(pir1.TMR1IF) {
pir1.TMR1IF = 0;
            pir1.TMR1IF = 0;
         
// charge pump
            // charge pump
if(charge_pump) charge_pump --;
            if(charge_pump) charge_pump --;
         
// EMERGENCY STOP!
            // EMERGENCY STOP!
if(E_STOP_IN) {
            if(E_STOP_IN) {          
run_state = STATE_E_STOP;
                run_state = STATE_E_STOP;              
E_STOP_OUT = 0;
                E_STOP_OUT = 0;
             
// turn off the laser
                // turn off the laser
ccpr1l = 0x00;  // power level to 0
                ccpr1l = 0x00;  // power level to 0
ccp1con &= 0xcf;  // power level to 0
                ccp1con &= 0xcf;  // power level to 0
laser_power = 0;
                laser_power = 0;
laser_on = 0;
                laser_on = 0;
LASER_ON_LED = 0;
                LASER_ON_LED = 0;
         
// turn off motors
                // turn off motors
portd = 0;
                MOTOR_EN=0;
portc &= 0x0f;
                portc &= 0x0f;


// LED flashing
flash = (flash + 1) & 0x07;
if(flash & 0x04) {
AMP_ENABLE_LED = 1;
}
else {
AMP_ENABLE_LED = 0;
}
}
// E STOP cleared - enter idle state
if(run_state == STATE_E_STOP && !E_STOP_IN) {
run_state = STATE_IDLE;
AMP_ENABLE_LED = 0;
E_STOP_OUT = 1;
}
// amplifier enabled - enter run state
if(run_state == STATE_IDLE && AMP_ENABLE_IN && charge_pump > 0x7f) {
run_state = STATE_RUN;
AMP_ENABLE_LED = 1;
ccpr1l = LASER_TICKLE;  // make tickle puses for the laser
ccp1con |= 0x30;  // PWM mode
}
// amplifier disabled - enter idle state
if(run_state == STATE_RUN && (!AMP_ENABLE_IN || charge_pump < 0x80)) {
run_state = STATE_IDLE;
AMP_ENABLE_LED = 0;


// turn off the laser
                // LED flashing
ccpr1l = 0x00;  // power level to 0
                flash = (flash + 1) & 0x07;
ccp1con &= 0xcf;  // power level to 0
                if(flash & 0x04) {
laser_power = 0;
                    AMP_ENABLE_LED = 1;
laser_on = 0;
                }
LASER_ON_LED = 0;
                else {
                    AMP_ENABLE_LED = 0;
// turn off motors
                }
portd = 0;
            }
portc &= 0x0f;
            // E STOP cleared - enter idle state
}
            if(run_state == STATE_E_STOP && !E_STOP_IN) {
                run_state = STATE_IDLE;
// handle laser power adjustments in run state
                AMP_ENABLE_LED = 0;
if(run_state == STATE_RUN) {
                E_STOP_OUT = 1;
// laser power adjust
            }
if(LASER_DEFEAT_IN) {
            // amplifier enabled - enter run state
// force laser into tickle
            if(run_state == STATE_IDLE && AMP_ENABLE_IN && charge_pump > 0x7f) {
ccpr1l = LASER_TICKLE;
                run_state = STATE_RUN;
laser_power = 0;
                AMP_ENABLE_LED = 1;
LASER_ON_LED = 0;
                ccpr1l = LASER_TICKLE;  // make tickle puses for the laser
}
                ccp1con |= 0x30;  // PWM mode
else {
                                //enable motors:
laser_power = (porta & 0x0f) << 4;
                                MOTOR_EN=1;
// if laser is on, change power immediately
 
if(laser_on) {
            }
ccpr1l = laser_power;
            // amplifier disabled - enter idle state
LASER_ON_LED = 1;
            if(run_state == STATE_RUN && (!AMP_ENABLE_IN || charge_pump < 0x80)) {
}
                run_state = STATE_IDLE;
}
                AMP_ENABLE_LED = 0;
}
 
}
                // turn off the laser
                ccpr1l = 0x00;  // power level to 0
// handle realtime run stuff
                ccp1con &= 0xcf;  // power level to 0
if(run_state == STATE_RUN) {
                laser_power = 0;
step_laser();
                laser_on = 0;
}
                LASER_ON_LED = 0;
         
// handle charge pump on rising edge
                // turn off motors
if(CHARGE_PUMP_IN && !old_ch_pump) {
                MOTOR_EN=0;
if(charge_pump != 0xff) charge_pump ++;
                portc &= 0x0f;
}
            }
old_ch_pump = CHARGE_PUMP_IN;
         
}
            // handle laser power adjustments in run state
            if(run_state == STATE_RUN) {
                // laser power adjust
                if(LASER_DEFEAT_IN) {
                    // force laser into tickle
                    ccpr1l = LASER_TICKLE;
                    laser_power = 0;
                    LASER_ON_LED = 0;
                }
                else {
                    laser_power = (porta & 0x0f) << 4;
                    // if laser is on, change power immediately
                    if(laser_on) {
                        ccpr1l = laser_power;
                        LASER_ON_LED = 1;
                    }
                }
            }          
        }
     
        // handle charge pump on rising edge
        if(CHARGE_PUMP_IN && !old_ch_pump) {
            if(charge_pump != 0xff) charge_pump ++;
        }
        old_ch_pump = CHARGE_PUMP_IN;
    }
}
}


void step_laser(void) {
// step inputs are low - reset the flags
if(!X_STEP_IN) {
x_step = 0;
}
if(!Y_STEP_IN) {
y_step = 0;
}
if(!Z_STEP_IN) {
z_step = 0;
}
// x step
if(!x_step && X_STEP_IN) {
x_step = 1;
// forward
if(X_DIR_IN) {
x_phase = (x_phase - X_STEP_SIZE) & 0x07;
}
// reverse
else {
x_phase = (x_phase + X_STEP_SIZE) & 0x07;
}
// phases
if(x_phase == 0) portd = (portd & 0xf0) | 0x05;
if(x_phase == 1) portd = (portd & 0xf0) | 0x0d;
if(x_phase == 2) portd = (portd & 0xf0) | 0x09;
if(x_phase == 3) portd = (portd & 0xf0) | 0x0b;
if(x_phase == 4) portd = (portd & 0xf0) | 0x0a;
if(x_phase == 5) portd = (portd & 0xf0) | 0x02;
if(x_phase == 6) portd = (portd & 0xf0) | 0x06;
if(x_phase == 7) portd = (portd & 0xf0) | 0x04;
}
// y step
if(!y_step && Y_STEP_IN) {
y_step = 1;
// forward
if(Y_DIR_IN) {
y_phase = (y_phase - Y_STEP_SIZE) & 0x07;
}
// reverse
else {
y_phase = (y_phase + Y_STEP_SIZE) & 0x07;
}
// phases
if(y_phase == 0) portd = (portd & 0x0f) | 0x50;
if(y_phase == 1) portd = (portd & 0x0f) | 0xd0;
if(y_phase == 2) portd = (portd & 0x0f) | 0x90;
if(y_phase == 3) portd = (portd & 0x0f) | 0xb0;
if(y_phase == 4) portd = (portd & 0x0f) | 0xa0;
if(y_phase == 5) portd = (portd & 0x0f) | 0x20;
if(y_phase == 6) portd = (portd & 0x0f) | 0x60;
if(y_phase == 7) portd = (portd & 0x0f) | 0x40;
}
// z step
if(!z_step && Z_STEP_IN) {
z_step = 1;
// forward
if(Z_DIR_IN) {
z_phase = (z_phase - Z_STEP_SIZE) & 0x07;
}
// reverse
else {
z_phase = (z_phase + Z_STEP_SIZE) & 0x07;
}
// phases
if(z_phase == 0) portc = (portc & 0x0f) | 0x50;
if(z_phase == 1) portc = (portc & 0x0f) | 0xd0;
if(z_phase == 2) portc = (portc & 0x0f) | 0x90;
if(z_phase == 3) portc = (portc & 0x0f) | 0xb0;
if(z_phase == 4) portc = (portc & 0x0f) | 0xa0;
if(z_phase == 5) portc = (portc & 0x0f) | 0x20;
if(z_phase == 6) portc = (portc & 0x0f) | 0x60;
if(z_phase == 7) portc = (portc & 0x0f) | 0x40;
}
// laser
if(LASER_IN) {
ccpr1l = laser_power;
LASER_ON_LED = 1;
laser_on = 1;
}
else {
ccpr1l = LASER_TICKLE;
LASER_ON_LED = 0;
laser_on = 0;
}
}
</pre>
</pre>



Revision as of 05:21, 9 March 2018

Laser Cutter Electronics

File:Laser-control board.pdf

File:Laser-motor driver.pdf


Laser control board pinout

Left Header: (Top to Bottom)

  • GND (Shield)
  • SW_1 (Yellow)
  • SW_2 ( Green)
  • SW_4 (Blue)
  • SW_8 (Lt Purple)
  • Disable (Lt Brown)
  • ...

Top Header: (left to right)

  • Output to LEDs
  • PWM output to laser tube (2 pins - black, red)

Bottom Header: (Left to right)

  • Laser EN (Black)
  • ...
  • (I/O to parallel port here)

Right Header: (Top to bottom)

  • ...
  • (Power Input & output to stepper driver)

Laser Power controller board pinout

Long header:

  • yellow = switch input
  • blue = parallel input
  • green = output to PIC (where switches used to go)

Top header:

  • Pin 1 (Orange wire) LASER_EN
  • Pin 3,4 - (Purple) Mode Switch
  • Pin 5 - Ground
  • Pin 6 - 5V


Code

When we replaced the motor controllers back in 2016; we moved the step generation logic off the PIC, and replaced it with a single "MOTOR_EN" output instead.

The original code changes have not been found, so the following is assumed but unvalidated.


/*
 * Laser Engraver Controller - ver. 1.1a
 *
 * Written by: Andrew Kilpatrick
 * Copyright: 2009, 2016
 *
 * Runs on PIC16F877A
 *
 * Functional Description:
 *  - support for connection to emc2 or similar host-driven CNC software
 *  - parallel port or other type of bit-bang connection to PC
 *  - E-stop and system run control support (amp enable, charge pump, etc.)
 *  - controls laser PWM control
 *
 * Hardware I/O:
 *  - RA0    - laser power bit 0        - input - active high
 *  - RA1    - laser power bit 1        - input - active high
 *  - RA2    - laser power bit 2        - input - active high
 *  - RA3    - laser power bit 3        - input - active high
 *  - RA4    - laser defeat            - input - active high
 *
 *  - RB0    - E stop loop            - input - 0 = run, 1 = stop
 *  - RB3    - motor_enable            - output
 *  - RB4    - laser activate        - input - 0 = off, 1 = on
 *
 *  - RC0    - amp enable LED        - output - 0 = off, 1 = on
 *  - RC1    - laser LED            - output - 0 = off, 1 = on
 *  - RC2    - laser PWM            - output - 0 = off, 1 = on
 *
 *  - RE0    - E stop output            - output - 0 = stop, 1 = run
 *  - RE1    - amp enable input        - input - 0 = disable, 1 = enable
 *  - RE2    - charge pump input        - input - high pulses to charge
 *
 */
#include <system.h>

#pragma CLOCK_FREQ 20000000

#pragma DATA 0x2007, _CP_OFF & _DEBUG_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _HS_OSC & _WDT_ON & _PWRTE_ON

// inputs
#define LASER_POWER_1_IN porta.0
#define LASER_POWER_2_IN porta.1
#define LASER_POWER_4_IN porta.2
#define LASER_POWER_8_IN porta.3
#define LASER_DEFEAT_IN porta.4
#define E_STOP_IN portb.0
#define MOTOR_EN portb.3
#define LASER_IN portb.4
#define AMP_ENABLE_IN porte.1
#define CHARGE_PUMP_IN porte.2

// outputs
#define AMP_ENABLE_LED portc.0
#define LASER_ON_LED portc.1
#define E_STOP_OUT porte.0

// laser setting
#define LASER_TICKLE 0x01

// run state machine
#define STATE_IDLE 1
#define STATE_RUN 2
#define STATE_E_STOP 3
unsigned char run_state;

// globals
unsigned char run;                // 1 = normal, 0 = stopped
unsigned char charge_pump;        // 0 = stopped, >0 = run
unsigned char old_ch_pump;
unsigned char laser_init;        // 1 = laser initialized, 0 = not initialized
unsigned char laser_power;        // laser power level
unsigned char laser_on;            // 1 = laser on, 0 = laser off
unsigned char flash;            // temp flasher variable

// function prototypes
void step_laser(void);

// main loop
void main() {
    // set up IO
    porta = 0x00;
    trisa = 0xff;  // inputs
    adcon1 = 0x06;  // all digital pins
   
    portb = 0x00;
    trisb = 0xF7;  // inputs except for MOTOR_EN
    option_reg.NOT_RBPU = 0;  // weak pullups
   
    portc = 0x00;
    trisc = 0x00;  // outputs
    AMP_ENABLE_LED = 0;
    LASER_ON_LED = 0;
    ccpr1l = 0x00;
    ccp1con = 0x0c;  // PWM mode
    t2con = 0x05;  // prescaler 4, timer on
   
    trise.PSPMODE = 0;  // no data port
   
    porte = 0x00;
    trise &= 0xfe;  // RE0 = output, RE1-2 = input
    E_STOP_OUT = 1;  // no E stop

    t1con = 0x21;  // 1:4 prescaler, internal clock, timer on

    // reset temp vars
    run = 0;
    laser_init = 0;
    laser_on = 0;
    flash = 0;
    run_state = STATE_IDLE;
    charge_pump = 0;
    old_ch_pump = 0;

    // bootup light dance
    AMP_ENABLE_LED = 0;
    LASER_ON_LED = 1;
    delay_ms(250);
    delay_ms(250);
    AMP_ENABLE_LED = 1;
    LASER_ON_LED = 0;
    delay_ms(250);
    delay_ms(250);
    AMP_ENABLE_LED = 0;

    // loop
    while(1) {
        clear_wdt();
       
        // do stuff every 50ms
        if(pir1.TMR1IF) {
            pir1.TMR1IF = 0;
           
            // charge pump
            if(charge_pump) charge_pump --;
           
            // EMERGENCY STOP!
            if(E_STOP_IN) {           
                run_state = STATE_E_STOP;               
                E_STOP_OUT = 0;
               
                // turn off the laser
                ccpr1l = 0x00;  // power level to 0
                ccp1con &= 0xcf;  // power level to 0
                laser_power = 0;
                laser_on = 0;
                LASER_ON_LED = 0;
           
                // turn off motors
                MOTOR_EN=0;
                portc &= 0x0f;


                // LED flashing
                flash = (flash + 1) & 0x07;
                if(flash & 0x04) {
                    AMP_ENABLE_LED = 1;
                }
                else {
                    AMP_ENABLE_LED = 0;
                }
            }
            // E STOP cleared - enter idle state
            if(run_state == STATE_E_STOP && !E_STOP_IN) {
                run_state = STATE_IDLE;
                AMP_ENABLE_LED = 0;
                E_STOP_OUT = 1;
            }
            // amplifier enabled - enter run state
            if(run_state == STATE_IDLE && AMP_ENABLE_IN && charge_pump > 0x7f) {
                run_state = STATE_RUN;
                AMP_ENABLE_LED = 1;
                ccpr1l = LASER_TICKLE;  // make tickle puses for the laser
                ccp1con |= 0x30;  // PWM mode
                                //enable motors:
                                MOTOR_EN=1;

            }
            // amplifier disabled - enter idle state
            if(run_state == STATE_RUN && (!AMP_ENABLE_IN || charge_pump < 0x80)) {
                run_state = STATE_IDLE;
                AMP_ENABLE_LED = 0;

                // turn off the laser
                ccpr1l = 0x00;  // power level to 0
                ccp1con &= 0xcf;  // power level to 0
                laser_power = 0;
                laser_on = 0;
                LASER_ON_LED = 0;
           
                // turn off motors
                MOTOR_EN=0;
                portc &= 0x0f;
            }
           
            // handle laser power adjustments in run state
            if(run_state == STATE_RUN) {
                // laser power adjust
                if(LASER_DEFEAT_IN) {
                    // force laser into tickle
                    ccpr1l = LASER_TICKLE;
                    laser_power = 0;
                    LASER_ON_LED = 0;
                }
                else {
                    laser_power = (porta & 0x0f) << 4;
                    // if laser is on, change power immediately
                    if(laser_on) {
                        ccpr1l = laser_power;
                        LASER_ON_LED = 1;
                    }
                }
            }           
        }
       
        // handle charge pump on rising edge
        if(CHARGE_PUMP_IN && !old_ch_pump) {
            if(charge_pump != 0xff) charge_pump ++;
        }
        old_ch_pump = CHARGE_PUMP_IN;
    }
}

Tube

The tube on the laser cutter is a 25W Synrad F48-2S

Manual for that version does not appear online, but here are manuals for newer ones: