Pinball Lamp Circuit

01 Jun 2011

Mbed Community

I have the following circuit wired up to pinball lamps:

/media/uploads/pinballer83/spi_relay_driver.jpg

Here is the code I am using:

//MOSI TEST PROGRAM
#include "mbed.h"

SPI device(p5, p6, p7); // mosi, miso, scK
DigitalOut pulse(p8);

DigitalIn sw1(p29); //define input pins
DigitalIn sw2(p30);


int main() {
    device.format(16,3); //16 bits, positive edge or something
    
       
    device.write(0x00);   
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0xFF);
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0x00);
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0xFF);   
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0x00);
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0xFF);
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0x00);   
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0xFF);
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    
    device.write(0x00);
    wait(0.75);
    pulse=1;
    wait(0.25);
    pulse=0;
    

I can't get the lamps to respond properly.

Any suggestions?

Cheers David

02 Jun 2011

This looks like it should work. The relays should toggle on and off every second for four cycles. What are you seeing as the actual behavior?

Other Comments:

1. For clarity, you might make the following changes to the bits of the program that write to the SPI port:

// Initialization
    device.format(16,0);   // 16 bits, clock idles low, data capture on rising edge
    pulse = 0;             // Initialize the latch signal
    device.write(0x0000);  // Write 16 bits of data to the SPI to clear the relay port
    pulse = 1;             // Latch the preceding data
    wait_us(1);            // Enforce a minimum inter-transfer interval

...

// Subsequent writes are as follows
    pulse = 0;             // De-assert the latch signal
    device.write(0xnnnn);  // Write 16 bits of data to the SPI
    pulse = 1;             // Latch the preceding data
    wait_us(1);            // Enforce a minimum inter-transfer interval
...

In the example above, the "pulse" signal is wrapped tightly around the actual SPI transfer. This is important if you are sharing the SPI channel with another device, because any data written to the SPI controller will be received by the simple parallel port circuit and the latch pulse will blindly capture the last data transfer. So you want to latch the desired data right after it is written, and not allow for the chance that a transfer to another device might squeeze in between the writing of the desired data and the assertion of the latch pulse.

The behavior just described will not cause a problem for you in your simple test program, but it could crop up as your hardware expands. Hence the suggested changes.

2. Have you checked the relay wiring to make sure it behaves as expected? For example, if you remove the wire that runs from pin 15 of U1 to pin 1 of U3, then connect pin 1 of U3 to +3.3V, relay 0 should activate.

03 Jun 2011

David,

If Hexley's code has not done the trick for you, I suggest that the next step is to use a test program for a 'divide-and-conquer' approach. The circuit in your schematic does not seem to have any timing constraints, so you should be able to check-out just the hardware side if you could 'wiggle' the three interface lines 'by-hand'. Once you are sure the hardware is working, you are free to concentrate on getting the software to match the hand-generated pattern(s) that worked.

The test program should operate as follows:

  1. Initialize the USB interface serial port to, say, 9600 Baud.
  2. Set all 3 of the interface lines to digital outputs.
  3. Send a sign-on message over the serial port (just to show that the software is running).
  4. Drop into a 'forever' loop that does the following on each pass -
    1. Check if an incoming character is available. If so then -
      1. Read the character (into a variable).
      2. Echo the character back on the serial port.
      3. Interpret the character (via a 'switch' statement) as follows -
        1. '0' (zero): set the data line low.
        2. '1' (one) : set the data line high.
        3. 'L': 'l': '2': set the clock line low.
        4. 'H': 'h': '8': set the clock line high.
        5. '-': set the latch line low.
        6. '+': set the latch line high.
        7. default: do nothing (gives a one character delay).

With the test program running, you can use a terminal program to set or clear each of the 3 signals (from the keyboard) and check the results with a voltmeter.

Next you can type (or cut-and-paste) strings of characters that should control the outputs of U1. Get just the Q1 output under control ("0HL+-+" vs "1HL+-+"), then all 8/9 (checking with a voltmeter). Then see if the U1 outputs are passing through U3. Type more (longer) patterns to check all 16 bits on all the IC's.

Finally, dump a large pattern from a text file to run a long sequence of bit patterns and waits. At 9600 Baud, the text file should be able to simulate a 240 Hz clock rate. At this point you should be confident that the hardware is all working. Try some higher baud rates if you wish (keep the test program and terminal settings matched :-)). Then move on to debugging your original software.

Checking the signals when under SPI control is best with an oscilloscope. Start with a loop that repeats a fixed pattern. If you do not have a 'scope, some multi-meters include a frequency counter that might help indicate parts of what is actually happening (i.e. clock frequency vs data and latch frequencies). With a low enough clock frequency (for debugging) you might even get by with a resistor and a speaker or headphone to probe the signals :-).

P.S. Your data and clock lines _DO_ have proper pull-up resistors?