Roy Ward
EE 499 Laser Electronics Independent Study.
Spring '96
The results of the improved optics and circuitry on the laser marking project started in EE 488. The optics, that finally arrived, greatly improved marking quality and surface power density. The redesigned control circuitry allows vector marking as well as raster marking giving the system greater flexibility.
The first laser marking project was designed to create a rastered image. The image was stored in an 8K EPROM and was a 'raw' 8-bit graphic file. The limitations of this design are its lack of flexibility and high memory consumption. The original design also had two other problems, the vertical advance didn't advance and the rastered image 'slipped' in relation to the table's position.
The first of the problems was solved; however, the redesigned control circuitry worked by an entirely different method and didn't use it. The more I have looked into the second problem the more it appears to have been an artifact introduced by transferring the program to the chip -- it was translated through many machines and some extraneous information may have been added.
To improve the flexibility of the system and its capabilities, I redesigned the control circuitry to allow it to create vectored as well as rastered images. Vectored images use memory only for the path that the laser actually follows and hence, larger images can be drawn with the existing memory. This method also allows the elimination of the jagged edges common to rastered images.
The new design required instructions to be encoded along with the image data, so the direct output of programs like Photoshop couldn't be used. For generating the information to be stored on the EPROM I developed two programs: one to insert instructions in 'raw' graphic files and one to create vectored line drawings and text.
The method of programming the EPROM also had to be improved since loading binary files with the 'Shooter' was nearly impossible (It would start receiving a file for only a few seconds after it was given the download instruction -- instructing the file to be sent, in a GUI like windows, takes slightly longer.) To solve this I used the Data I/O programmer. The Data I/O programmer accepts many formats, but not straight binary files, so I developed a third program to translate binary files into Data I/O's 'format 3'.
To convert the design to vectored laser marking it was necessary to redesign and replace almost all of the original control circuitry. Only about three or four chips remain untouched. To make file creation reasonable several programs were also created.
Block diagram of the control circuitry
The original stepper motor controller was a simple one, based on two JK flip-flops and some basic logic gates. The problem with it; however, was that it always applied power to two coils in the stepper motor, even when it didn't need to move. The design of this table doesn't require holding current so the power to the stepper motor can be shut off when no movement is occurring. By turning off the stepper when it's not moving a considerable current draw can be eliminated as well as the excessive heating of the transistors.
The new stepper motor controller is designed to turn all the coils off after a step if no new step has been triggered. The controller uses an eight state, state machine to decide what coils should be triggered. The first four states are for each of the four step positions. The second four states are to keep track of what position (which of the four steps) the motor is currently at, but turn off the drive to all the coils. When a step signal arrives the state machine jumps to the next 'on' state as indicated by the current position and direction. A zero to seven counter is used to determine when to switch to the 'off' states. If the counter reaches seven with no new step signal having occurred it changes to the corresponding off state.
ABEL 4.30 - Device Utilization Chart Fri Apr 19 12:28:16 1996The state diagram of the Stepper Motor Controller
Four phase stepper motor controller Type 3 ==== P22V10 Chip Diagram ==== P22V10 +---------\ /---------+ | \ / | | ----- | CLOCK | 1 24 | Vcc | | STEP | 2 23 | NEW_STEP | | DIR | 3 22 | CB | | | 4 21 | CA | | | 5 20 | PHASE_4 | | | 6 19 | PHASE_3 | | | 7 18 | PHASE_2 | | | 8 17 | PHASE_1 | | | 9 16 | QC | | | 10 15 | QB | | | 11 14 | QA | | GND | 12 13 | | | | | `---------------------------' SIGNATURE: N/A
module Stepper_Controller title 'Four phase stepper motor controller Type 3' STEPCTRL device 'p22v10'; "Input pins CLOCK pin 1; STEP pin 2; DIR pin 3; "Output pins QA,QB,QC pin 14,15,16 istype 'reg, buffer'; PHASE_1 pin 17; PHASE_2 pin 18; PHASE_3 pin 19; PHASE_4 pin 20; CA,CB,NEW_STEP pin 21,22,23 istype 'reg, buffer'; "Set definitions QSTATE = [QC,QB,QA]; STEP_0 = [0,0,0]; STEP_1 = [0,0,1]; STEP_2 = [0,1,0]; STEP_3 = [0,1,1]; WAIT_0 = [1,0,0]; WAIT_1 = [1,0,1]; WAIT_2 = [1,1,0]; WAIT_3 = [1,1,1]; COUNT = [CB,CA]; COUNT_0 = [0,0]; COUNT_1 = [0,1]; COUNT_2 = [1,0]; COUNT_3 = [1,1]; PHASE = [PHASE_4,PHASE_3,PHASE_2,PHASE_1]; state_diagram QSTATE state STEP_0: IF STEP & NEW_STEP & DIR THEN STEP_1 ELSE IF STEP & NEW_STEP & !DIR THEN STEP_3 ELSE IF (COUNT == COUNT_3) THEN WAIT_0 ELSE STEP_0; state STEP_1: IF STEP & NEW_STEP & DIR THEN STEP_2 ELSE IF STEP & NEW_STEP & !DIR THEN STEP_0 ELSE IF (COUNT == COUNT_3) THEN WAIT_1 ELSE STEP_1; state STEP_2: IF STEP & NEW_STEP & DIR THEN STEP_3 ELSE IF STEP & NEW_STEP & !DIR THEN STEP_1 ELSE IF (COUNT == COUNT_3) THEN WAIT_2 ELSE STEP_2; state STEP_3: IF STEP & NEW_STEP & DIR THEN STEP_0 ELSE IF STEP & NEW_STEP & !DIR THEN STEP_2^M ELSE IF (COUNT == COUNT_3) THEN WAIT_3^M ELSE STEP_3;^M state WAIT_0: IF STEP & DIR THEN STEP_1 ELSE IF STEP & !DIR THEN STEP_3 ELSE WAIT_0; state WAIT_1: IF STEP & DIR THEN STEP_2 ELSE IF STEP & !DIR THEN STEP_0 ELSE WAIT_1; state WAIT_2: IF STEP & DIR THEN STEP_3 ELSE IF STEP & !DIR THEN STEP_1 ELSE WAIT_2; state WAIT_3: IF STEP & DIR THEN STEP_0 ELSE IF STEP & !DIR THEN STEP_2 ELSE WAIT_3; state_diagram COUNT state COUNT_0: IF STEP THEN COUNT_0 ELSE COUNT_1; state COUNT_1: IF STEP THEN COUNT_0 ELSE COUNT_2; state COUNT_2: IF STEP THEN COUNT_0 ELSE COUNT_3; state COUNT_3: IF STEP THEN COUNT_0 ELSE COUNT_3; equations NEW_STEP := !STEP; A PHASE = [0,1,0,1] & (QSTATE == STEP_0) # [0,1,1,0] & (QSTATE == STEP_1) # [1,0,1 ,0] & (QSTATE == STEP_2) # [1,0,0,1] & (QSTATE == STEP_3); [QA,QB,QC,CA,CB,NEW_STEP].clk = CLOCK; end Stepper_Controller
Test results of the new stepper motor controller
The new stepper motor controller reduced average operating current by about 80% and eliminated heating of the coil driver transistors. Previously when one motor was not being stepped two coils were always left on. This resulted in about two amps current being drawn, about 10 watts being dissipated in the two coils and the transistors. Power loss in the transistor was high enough to rapidly make it too hot to touch. With the new stepper motor controller the temperature of the transistor does not rise detestably above ambient temperature.
To reduce etching time and improve apparent image quality new controls allowing the motion table to be vectored rather than just rastered were developed. To achieve this the data will be stored in the EPROM as an instruction followed by the data appropriate to the instruction. For a standard vector move this will consist of the instruction, the intensity, the direction (which quadrant), and the rise and run (0 to 15 / 0 to 15). This method is less efficient for use of memory per mark, but for simple vectored images uses less memory and time. Unlike raster imaging where a 'raw' graphic file from Photoshop could be used, a special program to translate an image to instructions is necessary. This program was written in C and allows generation of basic line art images. To maintain the ability to mark rastered images a 'start raster line' and 'stop raster line' instruction has been designed to allow efficient handling of rastered images. A simple program to tack the appropriate instructions on to the 'raw' graphic file to handle this was also developed.
A state machine has been designed to handle instruction processing and overall timing. The state machine has sixteen states and allows instructions over a range of lengths. The simplest instruction is the RESET instruction which sets the table back to a starting position indicated by a set of micro switches. The standard vectoring instruction reads the next two bytes and stores them in the appropriate registers. The 'start raster line' instruction keeps reading the next intensity byte and moving until the 'end of line' command is found.
The state machine has 32 states, 16 main states with the some states broken into two for timing reasons. The state machine handles three primary instructions; reset, load registers, and start a rastered line. It begins in the WAIT_INSTRUCTION state and when the NEW signal, indicating new data is ready, goes high it moves to the DECODE_INSTRUCTION state and if one of the three instructions is present on the INST lines it proceeds to the appropriate loop of states.
If the RESET instruction has been received then the START signal is sent repeatedly until either the X_RESET signal or the Y_RESET signal is received. When one of these is received it moves on to the next state and waits for the NEW signal, loads the next piece of data (move in the X direction, zero intensity). The next state again repeatedly sends the start signal until the X_RESET signal is received. The next two steps repeat this for the Y-direction. The state machine then returns to the WAIT_INSTRUCTION state.
If the LOAD_REGISTERS instruction is received then the intensity and direction data is loaded into register 1 and the 'rise over run' data is loaded into register 2. The final state in this instruction sends the START signal executing one move.
The START_RASTER instruction first loads the next byte then checks to see if it is the EOL instruction 0b1111. If it isn't the EOL instruction, it is loaded into register 1 and the START signal is issued. If it is the EOL instruction it returns to the WAIT_INSTRUCTION state.
The instruction decoder was originally designed to be connected to a serial port so the system could be driven by a computer for greater flexibility. The serial port was also designed, but more research is needed on my part; however, to make all the required programming aspects workable.
ABEL 4.30 - Device Utilization Chart Thu Jun 6 14:54:46 1996 Instruction Decoder and System Controller 4.3 ==== P22V10 Chip Diagram ==== P22V10 +---------\ /---------+ | \ / | | ----- | CLOCK | 1 24 | Vcc | | RESET | 2 23 | QSTATEE | | NEW | 3 22 | RESET_OUT | | X_POS_RESET | 4 21 | INC_PC | | Y_POS_RESET | 5 20 | QSTATEC | | INSTD | 6 19 | QSTATED | | INSTC | 7 18 | QSTATEB | | INSTB | 8 17 | QSTATEA | | INSTA | 9 16 | START | | | 10 15 | LOAD2 | | | 11 14 | LOAD1 | | GND | 12 13 | | | | | `---------------------------' SIGNATURE: N/AThe state diagram of the Istruction Decoder
module Instruction_Decoder_Controller title 'Instruction Decoder and System Controller 4.3' INSTCTRL device 'p22v10'; "Input Pins CLOCK pin 1; RESET pin 2; NEW pin 3; X_POS_RESET pin 4; Y_POS_RESET pin 5; INSTD, INSTC, INSTB, INSTA pin 6,7,8,9; "Output Pins QSTATEE, QSTATED, QSTATEC, QSTATEB, QSTATEA pin 23,19,20,18,17 istype 'reg, buffer'; LOAD1 pin 14 istype 'reg, buffer'; LOAD2 pin 15 istype 'reg, buffer'; START pin 16 istype 'reg, buffer'; INC_PC pin 21 istype 'reg, buffer'; RESET_OUT pin 22 istype 'reg, buffer'; "Set Definitions QSTATE = [QSTATEE, QSTATED, QSTATEC, QSTATEB, QSTATEA]; WAIT_INST = [0,0,0,0,0]; DECODE_INST = [0,0,0,0,1]; WAIT_LOAD1 = [0,0,0,1,0]; WAIT_LOADR = [0,0,0,1,1]; RESET_XY = [0,0,1,0,0]; LOAD_INTDIR = [0,0,1,0,1]; WAIT_LOAD2 = [0,0,1,1,0]; LOAD_ANGLE = [0,0,1,1,1]; START_LOAD = [0,1,0,0,0]; CHECK_EOL = [0,1,0,0,1]; LOAD_RASTER = [0,1,0,1,0]; START_RASTER = [0,1,0,1,1]; WAIT_RESET_X = [0,1,1,0,0]; RESET_X = [0,1,1,0,1]; WAIT_RESET_Y = [0,1,1,1,0]; RESET_Y = [0,1,1,1,1]; WAIT_INST2 = [1,0,0,0,0]; DECODE_INST2 = [1,0,0,0,1]; WAIT_LOAD12 = [1,0,0,1,0]; WAIT_LOADR2 = [1,0,0,1,1]; RESET_XY2 = [1,0,1,0,0]; LOAD_INTDIR2 = [1,0,1,0,1]; WAIT_LOAD22 = [1,0,1,1,0]; LOAD_ANGLE2 = [1,0,1,1,1]; START_LOAD2 = [1,1,0,0,0]; CHECK_EOL2 = [1,1,0,0,1]; LOAD_RASTER2 = [1,1,0,1,0]; START_RASTER2 = [1,1,0,1,1]; WAIT_RESET_X2 = [1,1,1,0,0]; RESET_X2 = [1,1,1,0,1]; WAIT_RESET_Y2 = [1,1,1,1,0]; RESET_Y2 = [1,1,1,1,1]; INST = [INSTD, INSTC, INSTB, INSTA]; state_diagram QSTATE state WAIT_INST: IF RESET THEN WAIT_INST ELSE IF NEW THEN DECODE_INST ELSE WAIT_INST; state DECODE_INST: IF RESET THEN WAIT_INST ELSE IF INST == [0,0,1,1] THEN WAIT_LOADR ELSE IF (INST == [0,1,0,0]) THEN RESET_XY ELSE IF !INSTD & !INSTC & INSTB & !INSTA THEN WAIT_LOAD1 ELSE WAIT_INST; state WAIT_LOAD1: IF RESET THEN WAIT_INST ELSE IF NEW THEN LOAD_INTDIR ELSE WAIT_LOAD1; state WAIT_LOADR: IF RESET THEN WAIT_INST ELSE IF NEW THEN CHECK_EOL ELSE WAIT_LOADR; state RESET_XY: IF RESET THEN WAIT_INST ELSE IF X_POS_RESET # Y_POS_RESET THEN WAIT_RESET_X ELSE RESET_XY; state LOAD_INTDIR: IF RESET THEN WAIT_INST ELSE LOAD_INTDIR2; state WAIT_LOAD2: IF RESET THEN WAIT_INST ELSE IF NEW THEN LOAD_ANGLE ELSE WAIT_LOAD2; state LOAD_ANGLE: IF RESET THEN WAIT_INST ELSE LOAD_ANGLE2; state CHECK_EOL: IF RESET THEN WAIT_INST ELSE IF (INST == [1,1,1,1]) THEN WAIT_INST ELSE LOAD_RASTER; state LOAD_RASTER: IF RESET THEN WAIT_INST ELSE LOAD_RASTER2; state START_RASTER: IF RESET THEN WAIT_INST ELSE WAIT_LOADR; state WAIT_RESET_X: IF RESET THEN WAIT_INST ELSE IF NEW THEN RESET_X ELSE WAIT_RESET_X; state RESET_X: IF RESET THEN WAIT_INST ELSE WAIT_RESET_X2; state WAIT_RESET_Y: IF RESET THEN WAIT_INST ELSE WAIT_RESET_Y2; state RESET_Y: IF RESET THEN WAIT_INST ELSE IF Y_POS_RESET THEN WAIT_INST ELSE RESET_Y; state WAIT_INST2: IF RESET THEN WAIT_INST ELSE IF NEW THEN DECODE_INST ELSE WAIT_INST; state DECODE_INST2: IF RESET THEN WAIT_INST ELSE IF INST == [0,0,1,1] THEN WAIT_LOADR ELSE IF (INST == [0,1,0,0]) THEN RESET_XY ELSE IF !INSTD & !INSTC & INSTB & !INSTA THEN WAIT_LOAD1 ELSE WAIT_INST; state WAIT_LOAD12: IF RESET THEN WAIT_INST ELSE IF NEW THEN LOAD_INTDIR ELSE WAIT_LOAD1; state WAIT_LOADR2: IF RESET THEN WAIT_INST ELSE IF NEW THEN CHECK_EOL ELSE WAIT_LOADR; state RESET_XY2: IF RESET THEN WAIT_INST ELSE IF X_POS_RESET # Y_POS_RESET THEN WAIT_RESET_X ELSE RESET_XY; state LOAD_INTDIR2: IF RESET THEN WAIT_INST ELSE WAIT_LOAD2; state WAIT_LOAD22: IF RESET THEN WAIT_INST ELSE IF NEW THEN LOAD_ANGLE ELSE WAIT_LOAD2; state LOAD_ANGLE2: IF RESET THEN WAIT_INST ELSE START_LOAD; state CHECK_EOL2: IF RESET THEN WAIT_INST ELSE IF (INST == [1,1,1,1]) THEN WAIT_INST ELSE LOAD_RASTER; state LOAD_RASTER2: IF RESET THEN WAIT_INST ELSE START_RASTER; state START_RASTER2: IF RESET THEN WAIT_INST ELSE WAIT_LOADR; state WAIT_RESET_X2: IF RESET THEN WAIT_INST ELSE IF NEW THEN RESET_X ELSE WAIT_RESET_X; state RESET_X2: IF RESET THEN WAIT_INST ELSE IF X_POS_RESET THEN WAIT_RESET_Y ELSE RESET_X; state WAIT_RESET_Y2: IF RESET THEN WAIT_INST ELSE IF NEW THEN RESET_Y ELSE WAIT_RESET_Y; state RESET_Y2: IF RESET THEN WAIT_INST ELSE IF Y_POS_RESET THEN WAIT_INST ELSE RESET_Y; equations LOAD1 := (QSTATE == LOAD_INTDIR) # (QSTATE == LOAD_RASTER); LOAD2 := (QSTATE == LOAD_ANGLE) # (QSTATE == WAIT_RESET_X) & NEW # (QSTATE == WAIT_RESET_Y) & NEW; START := (QSTATE == START_LOAD) # (QSTATE == START_RASTER) # (QSTATE == RESET_XY) # (QSTATE == RESET_X) # (QSTATE == RESET_Y); INC_PC := (QSTATE == DECODE_INST) & (([0, INSTD, INSTC, INSTB, INSTA] == WAIT_LOAD1) # ([0,INSTD, INSTC, INSTB, INSTA] == WAIT_LOADR)) # (QSTATE == LOAD_INTDIR2) # (QSTATE == START_LOAD) # (QSTATE == START_RASTER) # (((QSTATE == CHECK_EOL) # (QSTATE == WAIT_INST)) & (INST == [1,1,1,1])) # ((QSTATE == RESET_XY) & (X_POS_RESET # Y_POS_RESET)) # ((QSTATE == RESET_X) & (X_POS_RESET)) # ((QSTATE == RESET_Y) & (Y_POS_RESET)); RESET_OUT := (QSTATE == RESET_XY) # (QSTATE == WAIT_RESET_X) # (QSTATE == RESET_X) # (QSTATE == WAIT_RESET_Y) # (QSTATE == RESET_Y); [QSTATEE, QSTATED, QSTATEC, QSTATEB, QSTATEA, LOAD1, LOAD2, START, INC_PC, RESET_OUT].clk = CLOCK; end Instruction_Decoder_Controller
ABEL 4.30 - Device Utilization Chart Thu Jun 6 14:54:46 1996 Instruction Decoder and System Controller 4.3 ==== I/O Files ==== Module: 'instruct' Input files =========== ABEL PLA file: instruct.tt3 Device library: P22V10.dev Output files ============ Report file: instruct.doc Programmer load file: instctrl.jed
As I noted in the report for EE 488 the counter I used for this circuit was the wrong one, it was a BCD counter instead of a binary counter. The 4520 is identical pin for pin except it makes the full count from 0x0 to 0xF. With the proper chip in place the range of shades available is more than adequate. Intensities 0x0 to 0xF go from no mark to severely scorching most materials. The increase in power reaching the material due to this alone suggests that a much faster table movement could be used with the laser successfully.
Diagram of laser modulation circuitry.
The table direction is controlled in a similar manner as the laser modulation. The output from a 0x0 to 0xF counter (a 4520) is compared to the value stored in the register X or Y half of register 2 and the output gates the clock signal going to stepper motor controller. With this control any angle that can be described by a rise over run of 0 to 15 over 0 to 15 can be followed in each quadrant. The lower 2-bits of register 1 encode the direction (which of the four quadrants) the table moves. These values are directly connected to the direction inputs of the stepper motor controllers.
Diagram of ldirection control circuitry.
The timing is largely controlled by two sections of the control circuitry. The first is the crystal oscillator chip, a 2.4576 MHz crystal, and a 14 stage frequency divider / counter (a 4020). The Q13 output, 300 Hz, drives the stepper motor counter / timer. The Q13 output also drives the second 14 stage frequency divider / counter, which provides the clock signal to the instruction decoder state machine. The Q1 output, 150 Hz, of this second 4020 is used for full operating speed -- any faster and it out runs the system, where strange things happen. The Q1 output and a second output, chosen depending on what level of detail must be seen, are run through a toggle switch to select which to use.
The second timing circuit is the stepper motor counter / timer: once started it counts off 256 pulses to the stepper motor controllers. The 'counting' output is used to drive the NEW input of the instruction decoder, forcing it to wait until the motor finishes moving before starting the next instruction. The timer circuit used is the 'failed' variable length 8-bit counter from the original circuit. The inverted 'counting' and the 'clock_out' outputs handle the necessary timing.
The instructions for drawing the image, as before, are stored on an 8K 2764A EPROM. The EPROM programming this time was done using the 2900 Data I/O programmer. While ABEL, as far as I have found, isn't in itself useful for writing programs for EPROMs, its terminal program meshes well with Data I/O programmer. Due to this some method of generating data for the EPROM and transferring it to the programmer was necessary. The program BinToFm3 was developed to generate files the Data I/O programmer could load. The programmer itself, also, has a hex-editor that can be used to generate simple vector programs by typing the hex-code directly.
Once the files have been loaded, a fast process on the Data I/O machine, the EPROM is inserted into the circuit. The addressing is handled by a program counter that is incremented by the INC_PC output from the instruction decoder PLD. The program counter is made up of two counters, a 4520 and a 4020. The 4020 is a 14 stage counter / frequency divider, and would work by itself alone except, the Q2 and Q3 outputs don't have pins. To compensate for this the 4520, a 4-bit counter, fills in. The counters also have opposite triggering, the 4520 is positive-edge triggered, and the 4020 is negative-edge triggered, so an inverter is necessary to prevent a very odd counting sequence.
The outputs of the EPROM are connected to the two register's inputs as well as four lines go to the INSTA through INSTD inputs on the instruction decoder. I have use the most significant four since they aid in simplifying the programming. The middle or lower four may be better in the long run since they would allow the full intensity range to be used without a chance of triggering an EndOfLine accidentally.
To create images with the vectored laser marking system I have created three programs. The first takes the 'raw' graphic files from Photoshop and appends the necessary instructions for the vectored system to draw them as rastered images. The second creates vectored line drawings from commands, such as line and char. The third program translates the binary files, such as those created by the first two programs, and translates them into Data I/O's format three.
This program converts a binary file into Data I/O's format 3. The program creates the header, then the binary data is stored as ASCII 1s and 0s with an ASCII 'B' at the beginning of each byte and an 'F' at the end. An example of the output is shown below.
B00100000F B00000011F B00001111F B00110000F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B00000011F B11111111F B00100000F B00110001F B00001111F B00110000F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F B00110001F
The program then tacks on the ending codes after the data, and the file is ready. The largest problem with this format is its size. Eight kilobytes of data -- the size of the EPROM -- take about 92 K in this format. I haven't found a direct method of reading a binary file to the Data I/O programmer , but since it has about 100 formats one of them could be it. For any future work on this, format 4 encoding is more compact, but has error detection encoded into it that I haven't yet decoded -- it's more involved than just parity.
The program I wrote is uses C++, handling all I/O through the iostream libraries and functions. First the program asks for the input file, then the output file, followed by the length of the input file. The binary data will trip the iostreams End Of File incorrectly so the length of the file must be given and the .eof function ignored.
The program is made up of three .cpp files: BinToFm3, TranslateToFormat, and ReadStringSafely. ReadStringSafely was developed in a CSE course for homework. It allows a string of any length (memory permitting) to be read by using dynamic allocation techniques. BinToFm3 contains the main() function and handles getting the filenames and file length. TranslateToFormat is where the actual translation takes place. The input file is read using the .get function for file I/O to get 1 item at a time from the file. The << operator places the translated output in the output file as a type char. Type char is normally used for extended ASCII characters, so it outputs one byte at a time -- just what is needed here.
The RawToVectored program takes 'raw' 8-bit, gray-scale, graphic files and adds the necessary instructions so they can be marked using vectored laser marking. This program is very similar in layout to the BinToFm3 program (BinToFm3 was made from it). RawToVectored contains the main() function. The main() function calls GetFileNames.cpp which does what the name suggests, then main() gets the image size (rows and columns.)
'Raw' graphic file image as created by Photoshop (inverted).
The function in InsertPatternRTV2.cpp adds the necessary commands for the control circuitry and stores the file in tempFile. The file I/O is done using C++s file iostream functions. The file is read into a char variable using the .get function to get each byte separately. An entire row is read into an array. The first command 0x20, the load_registers command is written followed by the first, or last depending on direction, byte from the current row. Next the angle register is written, specifying full speed in the X direction and stopped in the Y. The command for raster_line is written, then the remainder of the image data, sans the last two bits in which the direction data is placed. Depending on the current direction the line is written in either forward or reversed order as is appropriate. At the end of the row of image bytes the EndOfLine command, 0xFF is given. Another load_registers command is given, this time with no intensity and in the downward direction to advance for the next line. This process repeats until all the rows are complete.
The next function is TranslateToFormat. This is the same function used in BinToFm3 and is a heavily rewritten version of InsertPatternRTV2.cpp. The input file is fixed, tempFile and the output file is that which was gathered earlier.
VectorDraw creates instruction files for vectored images. Two vectoring instructions have been implemented so far, line and char. A circle command exists only in stub form, is recognized but does nothing. The line command asks for the X and Y distance to move and the intensity. The following bit of code determines how to set the angle register, how many times to repeat the command to get a line of appropriate length, and what direction to use.
if (x == 0 ) { yMove = 15; xMove = 0; repeats = abs(y); } else if ( y == 0 ) { yMove = 0; xMove = 15; repeats = abs(x); } else if ( abs(double(x)/double(y)) < 1 ) { yMove = 15; xMove = abs(double(x)/double(y) * 15); repeats = abs(y); } else { yMove = abs(double(x)/double(y) * 15); xMove = 15; repeats = abs(x); } if ( x < 0 && y < 0 ) direction = 0; if ( x >= 0 && y < 0 ) direction = 2; if ( x < 0 && y >= 0 ) direction = 1; if ( x >= 0 && y >= 0 ) direction = 3;
The line command uses the raster_line command to draw lines over one move in length minimizing the instruction code length. Since the raster_line command is used the intensity must not be high enough, 0xFF to 0xF0, to trigger an EndOfLine. If the inst lines are taken from a different position this limitation in intensity could be eliminated -- the available range seems to be more than enough, so this isn't really a problem.
The other command, char, uses the line command to draw characters A through Z, 0 through 9, and special characters: ' . / space and backspace. A few letters have not been implemented since they weren't used and the same is true for some numbers. The characters are drawn without curves since this greatly simplified the coding, similar to 14 segment, alpha-numeric displays. Since the iostream functions eliminate white space, the '>' character is used for space and the '<' character is used for backspace.
The output for the file is also echoed to the screen, so the instructions generated can be seen and checked for errors. They are not an exact representation however because they are interpreted as short ints, two bytes instead of the one output as type char to the file.
Several improvements that could be made on this program include: an undo function, editing of existing files, text string entry, and circles. As the program exists if an error is made in entry it can't be removed or edited out, only compensated for. The best way to do this may well be to create a second file with the list of instructions. The underlying command routine came from a program originally designed to operate this way. The save function would need to be rebuilt, but the read function should work almost as is. Adding the capability to enter strings of characters would also greatly expedite the entry process and reduce the potential for errors. The circle function was created, but is only a stub, it should be relatively easy to make functional.
I started to create a program to draw on the screen, the vectored image store in a file. The problem I found; however, is that iostream functions do not work with proper Mac style C programming. The library I have created to make quick and 'easy' Mac style applications doesn't yet incorporate Mac file handling routines -- and I couldn't get them to work so far, so this will have to wait. A full GUI application combining the capabilities of the programs created so far would allow the flexibility of the system to be explored more thoroughly.
The accuracy of the table was high enough for all of the experiments attempted on it. This originally was of some concern since one rail had slipped out of parallel due to a construction mistake. The way the table operates it pulls itself back and forth along approximately the same line even in the wide area.
Suggestions for future projects include: building a small table and building a fast, very low friction and inertia table. Although now with vectored marking the potential of using the entire table is available; I haven't typically used more than a small area of it. A small table could also be built using different techniques enabling it to have much lower friction and much higher accuracy. This would be good for exploring the finest marking the system is capable of.
A fast, low friction and inertia table should also prove interesting to experiment with. With the circuitry now capable of controlling the laser over the full range of power, it could obviously move at a much higher rate of speed for many materials. Using a pulley and belt type drive would almost be a necessity to achieve the necessary speed using stepper motors. A cogged belt and pulleys, like those used in dot matrix printers, could give the necessary grip. The slide mechanism would then be attached to the belt in one spot. High quality, ball bearing, or wheeled bottom type, drawer slides would probably make a good mechanism for future EE 488/499 experiments.
Although the stepper motors I used were fairly high torque, as the project continued they seemed to have increasing difficulty. The Y-motor, that drives the lower slide, had to be switched out and replaced with the highest torque motor I had. Even with this motor some manual assistance was required to keep it moving. The problem turned out to be due to friction where the threaded rod turned in the threaded hole of the aluminum mounting block. With some lubrication the problem was largely cleared up. I would recommend using a graphite lubricant in the future. I would have used it, but couldn't find mine. After a while the oil softened the finish, making it sticky, counteracting the good it did.
Note drift in rastered image, wanted to drift right -- used manual correction and lubrication to keep under control.
Even with lubrication the motors were definitely strained when heavier loads were placed on the table. For future projects finding more powerful and new stepper motors could be worthwhile. The existing driver circuit with its MPT10N10Es is capable of driving 10 amps per coil, so the increased drive current could be handled. Using drawer slides or adhesive strips of a Teflon like material on the table might improve sliding. Another experiment could be looking into driving it with normal DC motors -- a closed loop control system would be necessary, however.
Previously the finest marks made by the laser were very light and had soft, 'fuzzy' edges. When power was increased to a reasonable level for visibility the mark was two to five millimeters across and still wasn't all that dark. With the beam focused by the spherical mirror in the top position, the beam width is about one millimeter, the size of the finest lines previously. The mark is also very well defined, with sharp, crisp edges and little or no effect on the surrounding material. The addition of the spherical mirror improved spot quality dramatically.
Anti - aliased image on the left, image on right not anti - aliased.
Laser marking of the images shown above, anti-aliased image on left, right image not anti-aliased. Slightly lighter portions of the anti-aliased image dissapear on laser marked image -- note the bottom of the Es in 'EE''.
The non-linear marking response of materials like wood has become very evident. The rastered image was anti-aliased by Photoshop in a linear fashion. When the rastered image is being laser marked, either only the darkest points show -- and some sections, lightened slightly by anti-aliasing, disappear, or the whole image blurs together and is unreadable. This non-linear response is due to the increased absorbency of the wood as the marking process darkens it. When the image was repeated without anti-aliasing the readability was much improved. The improved quality of the focused beam also appears to improve this.
Two holes in acrylic, the second is from the reflection of the laser off the aluminum backing plate.
Vector marking in acrylic, cut depth penetrates completely in most places. The discoloration is from the wood backing that was used during cutting.
Acrylic was the most interesting material to work with. The laser was very effective at vaporizing it, especially with the focused beam. At full power the laser punched a hole in the acrylic almost instantly. The first test actually put two holes in the acrylic, the first at the intended spot, and the second near by from the beam reflected off the shiny piece of backing aluminum.
The laser evaporates the surface with little effect on the surrounding material. The discoloration that occurred was mostly from evaporated wood gasses.
Vector marking on a painted metal surface, with and without focussing, at full power.
Effect of the laser on a painted metal surface, with focussing, at full power on one spot.
Probably the most effective way to mark metals with this laser is to mark a painted coating on the metal. With the laser adjusted to a level where it only burns away the painted surface and doesn't heat damage the surrounding paint it would make a good mark. Another good reason for using a lower power level, especially on thin metal, is to minimize the heat induced warping of the metal.
Even dull, sand blasted aluminum was not noticeably effected by the laser. As evidence of the reflected power from aluminum surfaces, the sheet of aluminum I used to protect the table on the first test of acrylic, vaporized the second, larger hole almost as quickly as the first (actually too quickly to notice that they occurred separately.)
The sample of anodized aluminum I used didn't appear to have been effected at all by the laser. Not even the anodization came off, although the bright spot of light was impressive. The type of anodizing may have been the reason for this, it was the dark brown colored coating from a section of window track material. The coating appears to be semi - transparent, unlike black anodized coatings, and may not absorb enough energy to be effected.
Vector marking on steel, close up on right.
Although it may not show up photographically the laser was able to etch the word 'VECTOR' into the surface of the steel plate I used. The mark was about a half millimeter wide, and could be felt due to the raised material on either side of the mark. The mark likely didn't penetrate the steel, but instead just removed the thin layer of oxides on the surface.
A controlled crack in glass on the left, damage caused by full power on left.
At full power the focused beam is capable of melting the glass. The cut was started about 0.5 cm from the edge and proceeded to about the same distance from the opposite edge. The table was following the vectored 'v' of 'vector marking', and at full power was melting part way through the glass, when it reversed for the second part of the 'v' the extra heat stressing explosively separated the glass into two pieces with the crack following the beam's path.
A scale solid surface approximation of the CO2 molecule.
The original laser used for this project was on loan from Yong Fang Zhang at Synrad. Since then, one was purchased by the department, and used for these EE 499 experiments. Synrad is a local (Bothell, WA.) laser company that provides most of the world's CO2 lasers. Their lasers are transverse, radio frequency excited, pseudo-waveguide lasers using extruded aluminum construction. The transverse excitation allows the use of higher gas pressures at lower excitation voltages resulting in less laser bore damage, a more stable plasma, and higher specific power. With the pseudo-waveguide laser only the outside of the beam interacts with the sides of the bore resulting in the advantages of a waveguide laser with fewer losses. The use of the extruded aluminum construction makes for a rugged, stable laser for a lower cost than other methods.
A photograph of the laser loaned by Synrad.
A photograph of the front panel of the new UC-1000 Laser Controller, showing: the new settings on the center knob, and the duty-ratio knob on the right.
The new laser and laser controller have many more features. The new controller, the UC-1000 Laser Controller, has a mode selector knob on the face panel for numerous new ways to control the laser. Standby (STBY) applies a tickle pulse to the laser keeping it ionized but, laser emission is not occurring. Two closed loop modes, high and low gain, allow a portion of the beam to be split off and the reading from a thermo-pile detector (48-CL) to regulate the laser's output power. Two remote control modes, as opposed to simple TTL input on the laser used previously, are available. One mode (ANC) allows remote current control. By varying the current between 4 and 20 mA, the laser output is varied from zero to maximum. The second remote mode (ANV) varies the power as the input voltage varies from 0 to 10V. Manual mode is still available with duty ratio set by the other knob on the face panel -- this is the method of control used previously. Gating the laser can be accomplished by applying a signal to the gate connector (a BNC type connector or the miniature phono jack next to it is an alternative) the laser's on power setting is set by duty ratio knob .
A photograph of the back panel of the new CO2 laser, showing: keyswitch, power LED, and lase LED.
The new laser has all the necessary safety features: an output aperture shutter, a keyed on switch and a five second turn on delay. The laser also supplies power for the power controller, so a separate supply isn't necessary. The DB-9 port on the side of the laser provides a means of monitoring the laser for fault conditions. The cap that comes in it is wired so that a fault, such as overheating will shut the laser off.
As before the laser is air cooled. Under the operating conditions of rastered or vectored marking on materials like wood the low duty cycle wasn't enough to heat the laser case above ambient temperature without forced air cooling. Vector marking in higher power density materials required the fan to keep it cool. A portable house fan on its medium or low setting provided the necessary air flow to keep the laser cool, even when vector marking metals.
Eye damage is a principle hazard of this laser so eye protection is important especially during alignment, and when working with possibly reflective materials. Unlike near IR. and visible lasers the eye doesn't focus its light on the retina so the chance of retinal damage or separation is minimized. The eye is also far more opaque to this wavelength, so eye damage is moved forward to the front surface, the cornea.
Two flat mirrors would allow the beam to be delivered to any spot on the table. Edmund Scientific carries gold coated mirrors with high reflectivity in the infrared that should be suitable for this project. For the final beam path only one was needed, since the table did the moving and X-Y movement of the beam was unnecessary. Beam size is relatively small within the project so their protected gold .500 in. by .707 in. mirrors #C32,273 should work (the smallest mirrors) .
Edmund Scientific's spherical, protected gold, one inch mirror with a four inch focal length was used for this project. (#C43,346 --again the smallest mirror.) Focusing the beam with this mirror greatly improved the quality of the mark.
CO2 Laser Beam Path, HeNe Laser Beam Used to Make it Visible.
The lasers interface accepts TTL signals to drive it, as well as has a control for direct varying of the duty cycle. The interface drives the laser with a 5 kHz signal pulse width modulated from 95% to 'tickle'. Tickle is a 1 us wide pulse to keep the gas ionized for quick turn-on times.
The table was constructed of MDF and maple wood since I am familiar with woodworking and have good variety of tools for working in the medium. Two stepper motors drive the table with threaded rods through tapped, aluminum plates. Coarser threaded rod and a different speed clock chip could also enhance its speed. Lubrication became an important factor, a powdered lubricant (like graphite) should be used since liquids soften the finish on the table, making it sticky, canceling the good of the lubrication.
The redesigned control circuitry greatly improved the flexibility of the system. Vector marking is a far quicker way of lettering and marking other line-type drawings. The redesigned circuitry is also set up for rastering images, and solved the vertical advance problem from the EE 488 controls. The text I used for demonstration was very simple, all straight lines -- no curves, but complexity is only limited by imagination and the time available to create fonts. Some fine tuning of the programs that create the vectoring instructions would improve the precision of marking. The motors don't travel as far for angled marks as they do for horizontal or vertical marks, which could be compensated for in the programming.
The addition of the curved mirror to focus the beam greatly improved spot quality. It no longer makes broad 'fuzzy' marks that blend into each other, but a sharply defined cut is made in the surface, with little or no effect on the surrounding material.
Acrylic, except for its toxic gasses was the material with the best response to laser marking. It vaporized quickly and easily leaving little or no residue. The laser would be an ideal method for cutting it into complex shapes. Acrylic also appears to respond to this laser as many materials would to much high power lasers and would make a good material for examining aspects of laser cutting. Hard woods were next, they marked well although there were some problems with build up of charred materials at higher powers -- the laser makes a really good, but expensive, wood burning tool. Soft woods were best for light surface marking, at higher powers their surface charred and generally did not respond well to the laser.
There are still many possibilities for future EE 488 / 499 projects in laser marking, and areas there wasn't time to explore. Improved programming, direct computer control, building a faster table are all design aspects that would be good to explore. Material processing aspects that would be of interest include: investigating further possibilities in acrylic and glass cutting, marking and separation.