Jump to content

Need some EE help with scanning switches

Recommended Posts

I posted this in another thread:

Well, I might as well tell how I'm supporting up to 100 switches with my Renesas design contest project. I've got 2 johnson counters. The first is clocked by a timer clock. The second is clocked with the first JC's carry output.


First, let's say I have only 10 switches and one JC. The JC's 10 outputs connect to each of the 10 switches. The other side of all the switches are tied together to one output, which is connected to a uC input pin. As the timer counts up, the timer clock output connected to the JC increments which switch gets power. If a switch is pressed, the uC gets a signal when the JC scans the depressed switch. As long as the timer counts to 9 and then resets to 0, the timer counter value will equal the switch that was pressed. I'd probably use a capture interrupt on the timer to get the switch number.


When I connect the second JC's clock pin to the first's carry output, I can use that with transistors to select which bank of 10 switches is being read. The timer ceiling should then be set to 99.


I don't know if this is clear without a schematic, or even a good way of doing things. I have some crudely drawn schematics at home I could scan in and upload if anyone wants.


When I posted that, I had the hardware built but hadn't tested it yet. I guess I skipped the all-important breadboarding step. Anyway, it doesn't work. Here's the schematic:



I hooked up my brand new logic analyzer, and saw that when I hit a switch, the output to the microcontroller stayed low. I expected it to only pulse low for the duration that the johnson counter was powering that particular switch.


My EE skill is pretty poor. I need to finish calc III before they'll let me learn it I guess. :D I'm hoping one of you guys could shed some light on the situation for me.


Oh, here's the link to the Johnson Counter's datasheet:


Link to post
Share on other sites

Man, I noticed my hardware is different from the schematic I've been staring at. I have that 1K resistor on the other side of the 2K2 resistor, by the base of the last transistor. This deserves an updated schematic, but I can't tonight. Don't worry about this thread for now. I'll get back to you tomorrow when I fix the discrepancy.



Link to post
Share on other sites

I guess it all depends on the manufacturer.


I think the problem is that the lower 4017 will always saturate one of the transistors no matter if the collector is at Vcc or not.

The current will flow through 2k2, T1, 2k2, and then the final transistor.

Another problem I see, if you push two switches at the same time, you will short 2 outputs of the top 4017 when one is high and other low.

How about something like this:



Other suggestions:

1. instead of transistors, use 10 open collector AND or NAND gates, 3 chips.

2. if you can live with 80 switches, how about multiplexer, like 74hc151 and a binary counter instead of lower 4017.

3. if 64 switches are enough, demultiplexer (74hc138), multiplexer and one 8 stage or two 4 stage binary counters.

Link to post
Share on other sites

Hey Rob, thanks for such a well-thought-out and complete answer. You raised a lot of good points and gave some good ideas. I guess the 2-switch short kills my original idea, even if I changed the transistor logic. The schematic you gave looks good. I think I'll either try that, use one of your other ideas, or maybe look around for other proven methods.


Kindof a bummer. I should have used a breadboard first.

Link to post
Share on other sites
...I guess the 2-switch short kills my original idea, even if I changed the transistor logic.

This can be fixed using diodes. In fact, even if you decide to use solution like 74hc138/151/393, you will still need diodes because 138's outputs are not open collector.


3 chips, 8 diodes, 8 resistors, 64 switches



this one uses 3 74hc03 open collector NAND gates, shown only 5, but you get the idea



last but not least, 64 switches with shift register and 6 pins, 3 to address 138, clk, latch, and serial in. 2 chips only.post-197-135135494616_thumb.png

Link to post
Share on other sites

Wow RobG, that's a lot of good stuff. Do you work with this kind of thing on a day-to-day basis?


I'd already started implementing your first schematic before checking back to see your later posts. It's a good fit for me as it requires the least amount of changes to my existing hardware, and doesn't require me to buy any new parts. I worked on it for an hour or two, but most of the time was spent de-soldering my previous work from the perf-board. I didn't leave myself enough room for the diodes.


I've already got some msp430 code for it, so I'll check back in when I get the hardware finished and tested.

Link to post
Share on other sites
...Do you work with this kind of thing on a day-to-day basis?

No, long time ago, when I was young and pretty, I spent a lot of time working with 74s. There were no PICs, MSP430s, etc., just things like Z80, 8255, and lots of 74s. Good old days.

Now I work as Java programmer for a big bad bank.

Link to post
Share on other sites

I wonder if something like this would work? 128 switches using 10 I/O pins, or 112 switches on 9 pins, etc.


Drive a pair of daisy-chained shift registers as a 16-bit (walking '0') ring counter. Reduce (or more correctly, spread out) driver overhead by sampling one "row" of eight switches during each 1-msec interrupt interval using simple parallel switch state logic to filter and flag the "new press" switch states. Each row will be sampled once every 16 interrupts effectively producing a 16-msec debounce interval.


Cheerful regards, Mike


  *  prep switch state latch and "new press" flags variables
  unsigned char swlat[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  unsigned char flags[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

  *  beep task produces a 32-msec 500-Hz beep (1-ms interrupts)
  if(beeptmr)                      // if beep task running
  { P2OUT ^= BIT0;                 // toggle piezo spkr on P2.0
    beeptmr--;                     // decrement msec beep timer
  *  sampling each matrix "row" at 1.0-msec interrupt intervals
  *  provides an effective debounce interval of 16-msecs.
  *  insert "new press" flag bits into the flags[0..15] array.
  *         ___---___---___---_____   invert active low switch
  *  swlat  ____---___---___---____   switch state latch
  *  delta  ___-__-__-__-__-__-____   changes, press or release
  *  delta  ___-_____-_____-_______   filter out 'release' bits
  delta = ~P1IN ^ swlat[row];      // changes, press or release
  swlat[row] ^= delta;             // update switch state latch
  if(delta &= swlat[row]);         // if any "new press" bits
  { beeptmr = 32;                  // task a "new press" beep
    flags[row] |= delta;           // insert "new press" flags
  *  prep for next matrix "row" interrupt
  if(++row == 16)                  // if last row
  { row = 0; dat = 0;              // reset row and insert a
  }                                // new "walking 0" bit
  clk = 1; clk = 0; dat = 1;       // shift the row select bit


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...