I recently acquired a nice Synrad CO2 laser for my laser cutter project. This laser has its power controlled by an opto-isolated PWM input. Synrad recommends a carrier frequency of 5 kHz. In addition they have a minimum duty cycle requirement, which they claim will possibly damage the laser if violated. The minimum duty cycle is 0.5%, which means 1.0 µs pulses at 5 kHz. They call these pulses 'Tickle Pulses'.
I needed a way to generate these pulses, as my laser did not come with the appropriate Synrad controller. I decided to program a PIC micro to perform this task, and like the Synrad controller allow me to set the power level with a potentiometer. I used a pic18f1220 for the task. This is my favorite microcontroller, and I've used it in many projects. I didn't need super high accuracy, so I opted to use the internal 8 MHz oscillator and no crystal.
First, to set the PWM frequency. I used timer 2 as the PWM clock. When using the 8MHz internal clock in the PIC, the basic instruction clock is 2 MHz. I set timer 2 to use that as it's clock source, with a /4 prescaler to give 500 kHz. Then I set the timer 2 period register to 99, meaning divide by 100, to get 5 kHz. So timer 2 repeatedly countes from 0 thru 99, resetting itself every 200 µs. The PWM works by comparing this timer to another register (CCPR1L, CCP1CON). It turns the PWM output on when timer 2 resets, and turns if off when timer 2 equals the CCPR1L value. Since timer 2 never exceeds a count of 99, setting the PWM duty cycle to any value greater than 99 will cause 100% duty cycle.
Now, the a/d convertor has 10 bits of resolution, giving values from 0 thru 1023. Since I need 0..99, I throw away the lo 3 bits of the a/d convertor value. This gives me a range of 0..127. To get full use of my potentiometer, I put a resistor in series with it so that when set to full scale, I get an a/d value of about 99. Then I added some math so that whatever the a/d value is, the PWM duty cycle will never provide pulses less than 1 µs.
Next, I added a pushbutton, connected to RA5. RA5 is normally the reset input, so I disabled the reset input and used the internal reset circuit instead. I also connected an LED to RA2. I setup the code for the LED so it blinks at a few Hz to indicate that tickle pulses are being generated. If I press the 'fire' button, the code uses the value from the potentiometer to set the PWM duty cycle, and the LED turns on continuously.
This works well. When the button is not pressed, the 'lase' indicator on the back of the laser lights up dimly, and there's no output from the laser. When I press the button, the 'lase' indicator lights up with brightness proportional to the duty cycle. When the duty cycle gets above a certain threshold, the laser action begins and you can hear a 5 kHz tone coming from it. The laser has an auxiliary DC output, so I used that to power the TPG. So as soon as the laser receives power, it also starts getting tickle pulses on its PWM input. The power supply has an enable input, so I can use that to switch power to both the laser and the TPG.
Ultimately, I'll use EMC to control this laser, and will connect a signal from it to the signal on RA5 so that the EMC G-Code can turn the laser on and off. Note that while this is intended for use with a Synrad laser, it should work fine with any of the Chinese disposable CO2 tubes that have a PWM input on their power supply. Here's the PIC source code for those interested:
I needed a way to generate these pulses, as my laser did not come with the appropriate Synrad controller. I decided to program a PIC micro to perform this task, and like the Synrad controller allow me to set the power level with a potentiometer. I used a pic18f1220 for the task. This is my favorite microcontroller, and I've used it in many projects. I didn't need super high accuracy, so I opted to use the internal 8 MHz oscillator and no crystal.
First, to set the PWM frequency. I used timer 2 as the PWM clock. When using the 8MHz internal clock in the PIC, the basic instruction clock is 2 MHz. I set timer 2 to use that as it's clock source, with a /4 prescaler to give 500 kHz. Then I set the timer 2 period register to 99, meaning divide by 100, to get 5 kHz. So timer 2 repeatedly countes from 0 thru 99, resetting itself every 200 µs. The PWM works by comparing this timer to another register (CCPR1L, CCP1CON). It turns the PWM output on when timer 2 resets, and turns if off when timer 2 equals the CCPR1L value. Since timer 2 never exceeds a count of 99, setting the PWM duty cycle to any value greater than 99 will cause 100% duty cycle.
Now, the a/d convertor has 10 bits of resolution, giving values from 0 thru 1023. Since I need 0..99, I throw away the lo 3 bits of the a/d convertor value. This gives me a range of 0..127. To get full use of my potentiometer, I put a resistor in series with it so that when set to full scale, I get an a/d value of about 99. Then I added some math so that whatever the a/d value is, the PWM duty cycle will never provide pulses less than 1 µs.
Next, I added a pushbutton, connected to RA5. RA5 is normally the reset input, so I disabled the reset input and used the internal reset circuit instead. I also connected an LED to RA2. I setup the code for the LED so it blinks at a few Hz to indicate that tickle pulses are being generated. If I press the 'fire' button, the code uses the value from the potentiometer to set the PWM duty cycle, and the LED turns on continuously.
This works well. When the button is not pressed, the 'lase' indicator on the back of the laser lights up dimly, and there's no output from the laser. When I press the button, the 'lase' indicator lights up with brightness proportional to the duty cycle. When the duty cycle gets above a certain threshold, the laser action begins and you can hear a 5 kHz tone coming from it. The laser has an auxiliary DC output, so I used that to power the TPG. So as soon as the laser receives power, it also starts getting tickle pulses on its PWM input. The power supply has an enable input, so I can use that to switch power to both the laser and the TPG.
Ultimately, I'll use EMC to control this laser, and will connect a signal from it to the signal on RA5 so that the EMC G-Code can turn the laser on and off. Note that while this is intended for use with a Synrad laser, it should work fine with any of the Chinese disposable CO2 tubes that have a PWM input on their power supply. Here's the PIC source code for those interested:
; ; tickle.asm ; ; Generate tickle pulses for Synrad laser ; list st=on ;dump the symbol table list n=9999 ;lines per page radix dec processor 18f1220 #include <P18F1220.INC> #include utility.inc ;noexpand list __CONFIG _CONFIG1H, _IESO_ON_1H & _FSCM_OFF_1H & _INTIO1_OSC_1H __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_32K_2H __CONFIG _CONFIG3H, _MCLRE_OFF_3H __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_OFF_4L __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L __CONFIG _CONFIG7H, _EBTRB_OFF_7H ; ; Declare RAM locations ; udata 0 duty_lo res 1 ;PWM Duty cycle ls bits duty_hi res 1 ;PWM duty cycle ms bits a_d_lo res 1 ;A/D convertor ls bits a_d_hi res 1 ;A/D convertor ms bits blink res 1 duty_min_lo equ 0x80 duty_min_hi equ 0x00 ; ; Reset and interrupt vectors ; org 0 ; Reset vector: 8 bytes goto main main movlb 0 ;initialize bank select reg rcall init clrf LATA idle btfss INTCON, TMR0IF ;Timer expired? bra idle_10 ;Branch if not bcf INTCON, TMR0IF ;Reset the flag incf blink,f idle_10 btfss PORTA, RA5 ;Is the button pressed? bra fire ;Branch if so movlwf duty_min_lo, duty_lo movlwf duty_min_hi, duty_hi rcall set_pwm_duty ;Set minimum duty cycle for tickle pulse btfsc blink,0 ;Should LED be on ? bra idle_20 ;Branch if so bcf LATA, RA2 ;Else turn LED off bra idle idle_20 bsf LATA, RA2 ;Turn the LED on bra idle ;; ;; The fire button is pressed. If the a/d conversion is done, read the value ;; and set the pwm duty cycle. Otherwise, use the most recent a/d value. ;; Then force the LED on. ;; fire btfsc ADCON0, GO_DONE ;Is A/D conversion complete? bra a_d_busy ;Branch if not a_d_done movff ADRESL, a_d_lo movff ADRESH, a_d_hi bsf ADCON0, GO_DONE ;Start another conversion movfw a_d_lo rrcf a_d_hi,f ;Divide by 2 rrcf WREG,w andlw 0xc0 movwf a_d_lo tstfsz a_d_hi bra a_d_busy btfsc a_d_lo, 7 bra a_d_busy movlwf 0x80, a_d_lo ;Clamp value at 1 usec a_d_busy movff a_d_lo, duty_lo movff a_d_hi, duty_hi rcall set_pwm_duty bsf LATA, RA2 ;Force the LED on bra idle init ;; ;; Initialize clock frequency ;; movlwf 0x72, OSCCON ;Internal 8 Mhz clock ; ; Initialize Port pins as inputs or outputs ; movlwf 0x21, TRISA ;RA0 is analog input. RA5 is pushbutton in. clrf PORTA movlwf 0x0, TRISB ;Set port B direction bits as described clrf PORTB ; ; initialize A/D convertor ; movlwf 0x7e, ADCON1 ;Make only channel 0 an Analog input movlwf 0x3e, ADCON2 ;Setup A/D timing, and left justify. movlwf 0x01, ADCON0 ;Turn A/D convertor on bsf ADCON0, 1 ;Start conversion ; ; Initialize Timer 2 for PWM ; movlwf 99, PR2 ;Setup PWM period for 5 kHz movlwf 0x05, T2CON ;Timer 2 on, /4 Prescaler call set_pwm_duty ; ; Initialize Timer 0 for LED blink ; movlwf 0xc7, T0CON ;Divide instruction clock by 256 return set_pwm_duty movff duty_hi, CCPR1L ;Set ms 8 bits of duty cycle rrncf duty_lo, w,1 rrncf WREG, w andlw 0x30 iorlw 0x0c movwf CCP1CON ;Write PWM mode and 2 ls bits return end
No comments:
Post a Comment