home about

Digital Input Technical Details

The Digital Input System consists of a hardware interface and a software queuing mechanism that makes it easy for hobbyists to build up elaborate home automation systems. A simple language is provided that allows easy programming of what will happen when any of the input buttons are pressed (or released). The software mechanism uses an interrupt signal from the Digital Input Board (or other device) to start the process. It determines which of the input signals have changed state (one or all of them), then creates "packets" on a queue for each changed input event. Part of the program periodically processes the packets. Any "handlers" that are of the correct type automatically get called to take the described action. This makes it easy to use the system for any purpose.

One example is an "evening mode lights" push button as part of a home automation system, but this could equally apply to bump sensors on your robot, limit switches in a factory process or sensors in your car. Connecting a push button to a microprocessor works easily enough if that's the only thing that needs to be monitored. A typical method is to connect the sensor input to an I/O pin on your controller. The input pin is then checked periodically. But in a system that is responsible for reacting to many external events, the controller may be busy processing something while the push button is pressed, the event could be lost and missed events are bad.

To make sure you never miss that event, you could connect a latch to the input. But the state of the latch still needs to be checked often so that the event can be handled in a timely manner. Another disadvantage is that your controller is spending time checking something that rarely changes state. If many inputs are to be handled, it can become impractical.

Another way to handle the push button problem is by tying it to the interrupt line of your microprocessor, but again, handling many inputs means that a way is needed to determine which input changed and what will happen if you get more events than expected? The system could be brought to its knees if it is spending all of its time in the interrupt handling state. Interrupt based methods can be tricky, too. It would be nice if there were a system to make this aspect much easier.

What is presented here is a method that uses a small interrupt service routine, in combination with an event queue, to capture events, such as push buttons being pressed. Event handlers and a simple language allows for flexible handling of these events. Using this system makes it much easier to build up a sophisticated system while the user programming is kept simple.

The Digital Input PCB Layout

The Digital Input Board described here will accept up to sixteen dry contact inputs. It will interrupt the processor if any of them change state. It doesnÂ’t matter if the inputs are normally open, or normally closed, or if they happen once a month or many times per second. Even if 6 inputs change state at the same time, all will be handled efficiently. The software remembers all the changes that have taken place.

For each device in the system, there will usually be some software (drivers and other code) that provides the means for easily adding a new type of device to the system. Users may wish to add their own creations to the system, or devices can be purchased on the authors web site. Typically, the driver for a device that can generate events will include an interrupt service routine which handles the external hardware event. Then events are added to the queues for other routines to process. A simple language is also implemented which provides a method to "script" actions by matching fields in the current event packet and creating new packets if a match is made.

The Digital Input Board is connected to the controller through a simple serial bus called SPI. Many devices may share the interface, and only 5 signal wires are needed to connect the digital input board to the controller. Even if your controller doesn't have SPI, it's not difficult to adapt any controller to use SPI devices. Some controllers have a similar interface which are also easily adapted. Any number of SPI devices may share the bus. Each SPI device shares the SCK, MISO and MOSI lines. A select line is provided for each individual SPI device so that only one is active at a time.

Digital Input Board Schematic (click here)

Figure 1 shows the block diagram for the digital input board. When an input changes state, an interrupt is generated as a result of the comparitors changing to a "not equal" state. The interrupt service routine for the digital input board causes data to be read from the MISO pin (Master In, Slave Out). The same data is then sent back in to the board via the MOSI (Master Out, Slave In), which causes the INT line to go high (normal state) clearing the interrupt state. A type "1000" packet is created and queued that reflects the data just read from the digital input board, which will be handled by the type 1000 handler.

The program "homesys" included here provides means for setting up a complete home automation system. It includes a way to write a script that allows creation of new packets when certain parameters match the current packet being processed on the queue. The new packets created can trigger things like the SPI-X10 interface to dim your lights. For example, a statement can be written that matches packets created by the digital input system, looking for one of the inputs to change state (perhaps connected to an "All Off" button). When the match is detected, the new packets defined in the statement are queued and subsequently sent to the SPI-X10 board, turning off all the lights in the house. This is a flexible system providing a working example of operation in a way that makes it easy to extend the system for more elaborate tasks. The example configuration script (cfg-table.txt) defines a number of push buttons that generate different types of X-10 events. The system works by comparing each event queue packet as it is being processed with each "statement" in the configuration script. When a match is found, the new packets defined (after the colon) in that statement are added to the queue as new events to be processed. These new packets can be packets destined for the SPI-X10 interface to dim your lights (1201 packets) or they can even simulate other push button events by generating different 1100 type packets! If any additional devices (and drivers) are installed, packets can just as easily be written for them.

Theory of Operation - Hardware
The digital input board described here contains parallel input shift registers, comparitors and parallel output shift registers. The comparitors compare the inputs from the screw terminals with the output of the parallel shift registers. The host controller will take the data last read from the board and write it back out to the parallel output shift registers, causing the comparitor to again be in the "A=B" state. The A=B output of the comparitor then indicates that both the data written to the board matches the state of all the screw terminals. The A=B signal is used as an interrupt to the host controller so the host controller can take action when any of the inputs change state.

The software also remembers the last state of each line, so that it can create a new event packet based on each bit that has changed state - if one or any number of them have simultaneously changed state. This scheme can be easily extended to monitor any number of inputs using additional digital input boards. All inputs have opto isolators to make it safe to string wire all over the place, reducing the risk of blowing any chips due to static electricity or lightning. The production boards have a header allowing TTL inputs to bypass the isolators if desired for applications that need a smaller board, and are only using nearby switch inputs such as with robots connected to bump sensors.

Theory of Operation - Software.
The program called Homesys is the main application program. It is made up of an assembler file, which contains the event queuing routines, and other library elements. Homesys.c is the main program file, and contains, among other things, the routines that handle the scripting language. To use the scripting features, a text file is written which describes events, such as push button presses, and what is to be done when these events are detected. The action to be taken is coded as new packets to be queued. These typically will trigger hardware devices such as the SPI-X10 interface which sends out X-10 codes to trigger light dimmers and such around the house. cfg-table.txt serves as a working example script. This is read in by homesys.c when "L" is typed at the keyboard while the main program is running. Comments and extra white space are stripped from the file, and is then stored in RAM.

Here's what happens when someone presses the "Evening Lites" push button in my living room. So the button is pressed. The Digital Input board's comparitor becomes out of balance (A<>B) since the new state of the screw terminals no longer matches the remembered state sent to the A side of the comparitors. Since the output of the comparitors drives the host controller's IRQ line, the Digital Input board's associated interrupt service routine (ISR) is called. This causes data to be exchanged with the board to obtain the current state of all the inputs. A 1000 type packet is created with this data, which is placed on the main queue. The newly acquired data (16 bits) is sent back to the board in a second transfer releasing the interrupt since the comparitor is again balanced, now that the data from the screw terminals read from the B side has now been sent to the A side of the comparitors.

A routine called check_queue is periodically called by the main routine in homesys.c. It should be called often in a loop. Each time it is called, one packet is taken from the highest priority queue and processed. The 1000 type packet generated by the interrupt service routine will be taken from the queue and offered to all the handlers in digxlib.asm to see if there is a matching handler. These handlers are generally looking for packets with "output" information that might cause action to some external device, such as the type 1201 packet for the SPI-X10 interface. In addition, the configuration script is also checked for matches. If any are found, the associated packets are added to the main queue.

There is a "1000" type handler which then processes the packet that was on the queue. It takes the data in the packet describing the new state of all the input lines and compares it with the last known state. For each input line that has changed state, a new 1100 type packet is queued. This packet type contains the input line number (0-15), and the state that it has just changed to (my living room Evening Lites button is input line #10). The routine check_queue continues to be called by the main routine. Eventually the 1100 packet that says that my living room Evening Lights button has just been pressed becomes the current packet being processed. The handlers are searched. There is one, but it only prints a message to the screen showing which lines have just changed state (Line number 10 is now 1). The configuration script is checked, and there is a matching "statement" that looks for packets of type 1100, with the first data byte matching input #10 (0A in hex) and the second byte equaling 1. Since this statement matches, everything following the colon and up to the semicolon, are taken as new packets and they are placed on the queue. Four new packets - of type 1201 are queued. These are SPI-X10 output packets. When check_queue is again called, the first of the new 1201 packets gets processed. The 1201 handler is activated which selects the SPI-X10 board, and sends the data contained in the SPI-X10 board. This first 1201 packet says to dim two of the dimmers to the off position. I do this first in order to put the lights in a known state before sending a bright command to bring them to the desired level. Someone could have dinked with the lights since the last command was sent to that unit. There are a number of ways to do this depending on your taste. The process continues until all of the four packets that were queued have been processed. If no other external events have occurred, then the queue will be empty and nothing more happens until the next external event occurs.

J1 Pins
SPI Header
1 +5V
2 Gnd
6 SPI clock
8 SPI serial input
(from controller)
10 SPI serial output
(to controller)
11 Dig-In select
(active LOW)
14 IRQ Disable
(debugging aid)

Table 1. J1 SPI connector pins. Only pins listed are used on the 14 pin header.

There are actually two event queues, though this is largely transparent to the user. The normal queue is most often used. The second, high priority queue is mainly for event processors that create other events, which should be handled before any other events are handled. The check_queue routine always returns with the highest priority event. In the case of the digital input board, one ISR-generated event could potentially be turned into many events (line 1 on, line 5 off, line 6 on, and so on). However, if these were simply added to the end of the main queue, they might be placed after some other hardware-generated event that happened after the digital input event. They would be processed out of order. By placing events created as the result of other events on a special high priority queue, the order of events can be maintained.

Construction. Refer to the layout diagram Figure 3 for assembly. The passive components R1 and C1 through C7 should be installed first. Note the polarity of C1. Next, install J1. If the connector used for J1 has a polarity mark, be sure this goes into the square pad indicating pin 1 (this might be indicated by a triangle on the outer casing. The board can be cleaned at this point, before sockets and other components that could get flux in them are installed. Sockets should be used at least for the SIP resistors, RP2 and RP4, since these control how much current goes through the external contacts. Sockets make it easy to change these resistors if it is desired to alter the current supplied through external wires, through contacts at the other end and ultimately to the LEDs in the opto isolators. An ammeter can be used to verify loop current which can be compared with the manufacturer's data sheet for the exact optoisolator used. But generally, when a switch input is closed the loop current should be somewhere between 5 and 15mA. The current limiting resistors RP2 and RP4 have been chosen as reasonable values, and should work for local push-buttons or ones located 20 feet away. However in certain situations the loop current might be lower than normal due to additional resistance in the loop due to long wires, or high-resistance contacts. Lower values for RP2 and RP4 could then be used to compensate.

Sockets should also be used for the opto isolators U9 though U12, because if some nasty spikes come down the long wires, and an opto isolator gets fried, it is easily replaced. Install the terminal strips TS1 and TS2 (or the header part if the two-piece connectors are used). Clean the board, if desired, being careful not to get solvent and flux in any sockets or connectors. Next, plug the socketed components in using layout diagram Figure 3.

In the authors prototype two-piece terminal strips were used for TS1 and TS2 (Phoenix p/n 17-57-09-3 terminals and 17-57-32-3 matching PCB headers). The artwork accommodates the single piece type as well (Phoenix p/n 17-29-20-9). Actually, any terminal strips can be used that have 0.2 inch spacing between the PCB pins.

As with any electronics assembly project, very carefully inspect your work before applying power for the first time. Look closely, since it is very easy to look right at a solder bridge an not see it, so spend at least a couple minutes searching for errors carefully.

TS1 terminals
1line #1
2line #2
3line #3
4line #4
5line #5
6line #6
7line #7
8line #8
TS2 terminals
1line #9
2line #10
3line #11
4line #12
5line #13
6line #14
7line #15
8line #16

TS1 and TS2 terminal strip connections

Test and Operation.
To test the Digital Input Board you will need a controller. The SPI connector is designed to plug into Zorin's ModCon (noted in the parts list) which is a general purpose controller based on the Motorola MC68HC11E9 microcontroller. Any computer or microcontroller can be used, as long as it has four available I/O lines (Select, Serial in, Serial out, Clock) plus an interrupt input. This article and the included software assume the board is plugged directly into the ModCon. Power to the digital input board is supplied from the ModCon through the SPI cable. Both the SPI-X10 board and the Digital Input board are plugged into the ModCon using a 14 pin cable with three connectors. The select lines from the two peripherals use different select lines in the cable to avoid conflict.

A test button or switch should be connected to either TS1 or TS2 between any input line and ground. Ground connections are provided on the screw terminals.

Two test programs are provided to assist checkout. The files mentioned here are available in the archive dig-in-test.zip. To perform a simple test to check out the basic operation without using interrupts, assemble and load digtest1.asm. Or, pre-assembled files are available, to save time, as digtest1.s19 and digtest1.lst. How the resulting ".s19" file is loaded will depend on the processor used. (ModCon users will typically use the Buffalo Monitor command "LOAD T"). The ".s19" file is then uploaded through the terminal program's text upload feature, or through the cut and paste method.

When this program is run by typing "call 8000," it will continuously display the state of all the inputs. The display should change as the test switch connected to an input line is pressed and released. Also, as the test switch is pressed and released, pin 19 of U3 (A=B output of comparitors) should go from logic 0 to logic 1 briefly, then return to logic 0, indicating that the correct data is being loaded, and then sent to the board thus balancing the comparitors.

>call 8000
11111111 11111111
11111111 11111111
11111111 11111111
11111011 11111111
11111011 11111111
11111011 11111111
11111111 11111111
11111111 11111111
11111011 11111111
[reset pressed]

Example 1. This screen shot shows digtest1 in operation.
The 0's appear during the time line #11 is grounded in this example.

Once the basic operation of the board has been checked, the next step is to verify operation using the interrupt system and basic queue operation. Assemble and load digtest2.asm. Or use the pre-assembled file digtest2.s19 The assembler listing, digtest2.lst, can be used for reference. Digtest2 demonstrates a more "real time" response system. When running, any changes to the input lines generates an interrupt. The Interrupt Service Routine (ISR) communicates with the board, obtains the latest state of all the lines, then sends the same data back to the board in order to balance the comparitors and reset the interrupt line (derived from pin 19 of U3). Rather than do something directly, the ISR simply creates an "event packet" and places it on the normal event queue. The benefit of this scheme is that the ISR doesn't have to know anything about what the event means. This "event" (a 1000 type packet) simply means that something on the board changed, here's the new state of all 16 inputs. It is usually important to keep the amount of programming inside interrupt service routines as small and fast as possible for the best overall system response. The digital input system does this by doing nothing more than creating a packet on a queue - then it's finished. Note that this test program uses 8 byte event packets while the next program, Homesys, uses 16 byte packets.

>call 8000
Line #1 is now 0
Line #2 is now 0
Line #1 is now 1
Line #2 is now 1
[reset pressed]

Example 2. This screen shot shows digtest2 in operation. Dots are printed to
show the program is running. As line #1 and #2 is connected and disconnected
from ground, events are queued and ultimately printed as state changes.

It's interesting to try out the system, then take a look at the data in the actual event queues to see the results of the test. The memory areas that the queues occupy can be filled with some value before the run, so that the queue activity is more obvious. The command "bf 9000 91ff aa" will block fill both queue areas with the value "AA." The normal queue is set to start at address 9000, while the high priority queue is immediately after it, at address 9100, therefore this command fills both in one step. Any value can be used, but an unlikely value to appear in the packets is best such as hex value AA. Note that digtest2.asm uses smaller 8 byte packets.

>md 9000

9000 10 00 00 00 3F FF 00 00 10 00 00 00 3F FF 00 00 
9010 10 00 00 00 FF FF 00 00 AA AA AA AA AA AA AA AA

>md 9100

9100 11 00 00 00 01 00 00 00 11 00 00 00 02 00 00 00
9110 11 00 00 00 01 01 00 00 11 00 00 00 02 01 00 00

Example 4. Displaying data in event queues
showing the 1000 type events on the normal queue and the
resulting 1100 events on the high priority queue

It's now time to test the whole system together and decide how you want use the input lines and X-10 devices or other devices connected to the system. A simple script should be written to verify operation in the user's environment. Start by unpacking homesys.zip, which contains all the files that make up homesys. If you are using the setup described in these articles, you can skip to the next paragraph. The Readme file contains information on all the files in the archive, how to compile your own version and about and setting up the system for your own push button activated lighting system. If you intend to modify either homesys.c or digxlib.asm, install ICC11 version 0.48. This is a freely available C compiler for the HC11 microcontroller. (available on the ModCon diskette or by doing a web search for "ICC11.")

To run homesys, first load the homesys.s19 file included in the archive, or compile your own. Upload the program as with the previous examples. Issue the command "call 9500" to start the program. Period characters should start zipping across the screen. Now, upload the configuration file by pressing "L," then send the configuration file (using ASCII upload or the cut and paste method). After the successful upload, trigger an input line that has an action defined for it in the configuration file. Packets should be queued, and the desired operation should take place. Lines on the terminal screen should look similar to example 2 above.

Expanding the system.
You probably want to do more with the system than controlling X-10 devices from push buttons. The Homesys program has been written to be flexible and expandable which makes it easy adapt the basic system to your needs. Some things to consider adding to the system might be: A photo transistor added to one of the host controller's analog input's can make a convenient way to trigger lighting modes based on sunset, a Real Time Clock IC, such as MC68HCT1 can be added to the system to allow triggering events by time of day, relays that can easily be added by using another SPI chip, the MC33298 which can directly drive inductive loads, such as relays, solenoids or valves using the SPI bus. Check our site at http://ZORINco.com for application notes and additional information, and other compatible devices. The latest version of this software is available there as well.

Copyright 1986-2019   Zorin   Seattle, WA   (206) 282-6061