William A. Leonard

Computer Consultant

3D Scanner


Part 2 - Electronics (continued)

With the completion of the motor sequencer and clock circuits, what remains is to construct the interface circuitry so that the scanner can be controlled from the computer. The various components need the capability of being individually addressed and switched on and off.

Below is a schematic of the parallel port interface. It's currently undergoing testing. So far, handshaking is working properly and the Laser Tracs® are under software control. Next, I'll test that the relays and counters are properly addressed.

Parallel Port Interface

U1 and U2 are buffers which are wired to the parallel port cable. U1 buffers the 8 data lines and U2 handles ~STROBE. U2 also handles status lines ~ACK and BUSY. The limit switch status is also brought out through U2.

The main purpose of U5 is to synchronize the STROBE with the clock. The step counters (74LS191 - shown below on another sheet) require loading while the clock is high. U5 insures that the clock will be high when the enabling signal (out of U5 pin 2) triggers the event.

U5 also sends back the handshake signals. I differ from the literature by acknowleging the strobe on the same rising clock. The literature shows that the acknowlegement is sent at the conclusion of the device's busy state - which for the scanner may be several seconds. My plan is to ~ACK the ~STROBE and use BUSY for the duration of the operation. U5 asserts BUSY along with ~ACK. In most cases, the computer will drop the ~STROBE on seeing ~ACK and, on the subsequent rising clock, U5 will drop ~ACK and BUSY. If the counters are busy counting steps, they will hold BUSY (via U6D) until the count is finished.

U1 handles the 8 parallel port data lines. Because the scanner needs several individually addressable components, the data lines are divided into 4 lines of data and 3 lines of address with the extra line ignored.

U4 selects among 2 counters and the latch. The counters are individually loaded with a 4-bit starting count which is provided by the low order 4 bits of the parallel port data. As drawn in the schematic, to set a count of 243 steps, the computer would output the high order nibble to counter 2 (0x2f) and the low order nibble to counter 1 (0x13).

U3 is able to hold 8 one-bit values to switch on and hold some simple on/off circuits. The latch is addressed as the counters were except that it is selected with the high order nibble of 0 (so that U4 selects U3) and the low order nibble contains the device number and its value. For instance, Motor Voltage 1 is turned on by
     0x5 = 0x0 (the latch)
         + 0x4 (MV1)
         + 0x1 (on)

U3 controls several devices using TTL levels: stepper motor direction, sequencer (stepper motor) selection, mode (counted or free running operation) and "GO". The Laser Tracs® are individually controlled by U3 but the TTL level outputs drive transistor switches to turn each one on and off. Motor control outputs also drive transistor switches which, in turn, drive relays to switch high voltage on and off.

I put in the motor relays because the transistors and the motors build up heat very quickly and I was concerned about the drain on the power supply. I expect there to be periods when the motors would be idle and to leave them powered on seems inefficient. Because the motion is all horizontal, there is also no need for the motors to hold position when friction is enough. I'll work out the scheduling for applying power later.

When the entire scanner was assembled and the various components tested, I discovered that turning one of the motors on (5v, 1 amp) caused the latch to drop one or both of the Laser Tracs®. I added a bypass capacitor between the Vcc and Ground pins and the problem went away.

Another problem was that, while the handshaking was working well, the component devices wouldn't always turn on. I inserted delays into the computer's output stream and the problem disappeared. The final solution was to make the scanner's clock available on a parallel port status bit and synchronize the computer's output stream with it.

On/Off Controls

The counting circuit consists of a pair of 74LS191s. They are loaded with a pair of 4-bit values and allowed to count down. While counting, an "in-progress" status holds BUSY status high and is an alternative to free-running operation (at U4A).

Counters

The circuit board pictured below is the composite of the parallel port interface, clock, addressing, and counter circuits.

Interface

handshake (18K)

Here is an oscilloscope trace of the handshake lines. Ignore trace 7... it's unused and trace 8 is a line I used to trigger the data capture and to mark the beginning and end of the handshake sequence and is not really part of the handshake.
Don't try to measure timing intervals: the data and signal lines are sampled by a slow clock which is not in phase with the scanner's clock. (Note the unequal intervals in the clock trace!) A faster clock would have more precise timing but the storage capacity of the logic analyzer would be exhausted too quickly to record the entire sequence.
At point A, the computer asserts the data and shortly thereafter, at point B, signals the ~STROBE.
At point C, the next rising clock on the scanner latches the ~STROBE (~STROBE') and causes ~ACK and BUSY to be sent to the computer in response to the ~STROBE. The computer releases the ~STROBE. The computer then signals another trigger on line 8 to mark the end of its participation in the handshaking at point D.
The scanner, however, is still asserting BUSY until the next rising clock at point E where it releases ~STROBE' and drops BUSY and ~ACK.

The code below was tailored to generate the handshake waveforms. As discussed above, the scanner components did not respond well unless the outputs were synchronized to the scanner's clock which, here, they are not.

Inp32 and Out32 are functions exported from Inpout.dll available from www.logix4u.net. This library makes it possible to do direct reads from and writes to the parallel port.

void CScannerView::PortOutput(BYTE byte)
{
     do {                             // Wait for not BUSY
          m_status = Inp32(STATPORT); // BUSY is inverted in hardware !
          } while (!(m_status & BUSY));
    
     Out32(DATAPORT, 0x02);           // Set up logic analyzer Trigger
     Sleep(5);                        // Insert separation in oscilloscope trace
     Out32(DATAPORT, byte);           // Set up DATA        POINT A
     Sleep(5);                        // Insert separation
     Out32(CTLPORT, STROBE);          // Assert STROBE      POINT B
     do {                             // Wait for ACK
          m_status = Inp32(STATPORT); //                    POINT C
          } while (m_status & ACK);
     Out32(CTLPORT, 0);               // Take down STROBE   POINT C still
     Out32(DATAPORT, 0x02);           // Set up Trigger
                                      // (for oscilloscope marker)
     Sleep(5);                        // Separation
     Out32(DATAPORT, 0x00);           // Release Trigger    POINT D     
     }
            

10/25/06

Home
Part 1 - Mechanics
Part 2 - Electronics
Part 3 - Software
Part 4 - Summary