1 Switch per pin? Analog or Digital?

Started by swinginguitar, October 02, 2011, 09:06:42 AM

Previous topic - Next topic

swinginguitar

Concerning PICs, if you were to have a number of momentary switches trigger an interupt, do you need 1 pin per switch, or is there a way to have a single input to the PICs ADC recognize which (single or several) has been pressed (resistor ladder etc)?

Is ADC the way to go for this, or would you just configure a bunch of pins as digital and have the switches toggling each between 0v and +5v?

nexekho

Although this is Arduino, therefore Atmel not PIC, as far as I know the same principles should apply:
http://www.arduino.cc/en/Tutorial/Switch
For one switch per IO pin
http://www.arduino.cc/en/Tutorial/ShiftIn
For multiple switches per IO pin

If you only needed one switch at a time, you could hook them up to multiple inputs so A would trigger 0 but not 1, B 1 but not 0, and C 0 and 1 and so on giving (2^IOPorts)-1 single inputs.  Not looked into how that'd correspond with the pulldowns, etc. which I think are needed
I made the transistor angry.

R.G.

Getting as many functions per pin as possible is a time-honored cottage industry for PIC users. There are many ways. Using three pins for a substantially unlimited number of switches as mentioned is probably the densest, but requires an additional CMOS part for every eight or so switches. Using a switch-matrix approach gives you N*M switches for N+M pins, which effectively scales as N2/(2*N). Going with ADC gives you many switches on one pin, but the analog accuracy of your resistor network limits the number of switches which can be reliably detected.

These schemes only address scaling up the number of input switches, not the number of output bits or indicators.

I like my scheme. It's not the best, necessarily, but as the saying goes, a poor thing but my own. I use a single pin to both read a switch press *and* run the indicator LED for the switch state by having the pin mostly run the LED, but shift into input for a few microseconds every so often to see if the momentary switch is closed or open.  I found that for footswitch work, I nearly always wanted an LED per switch, so it was handy to have the outputs per switch scale up with the number of switches.
R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

MoltenVoltage

The main problem with using the ADC as a multiple switch input is with writing decent debounce code, which is hard enough using a single switch.

The way I do it is with a couple pins and diodes, so a single switch pulls down a fixed combination of pins.

It really depends on the kind of switch - momentary vs. toggle.  With toggle switches, the ADC thing makes (some) sense, but with momentary switches, I think you are asking for problems.
MoltenVoltage.com for PedalSync audio control chips - make programmable and MIDI-controlled analog pedals!

swinginguitar

Thanks for the replies...I'm digging in now....

R.G. - using your method, how are your pins configured - are they set to digital and are listening for a jump to/from logic hi/lo? Are you driving the LED directly from the output pin, or do you amp it up for extra current?

I studied out some of your articles, and was initially going to try the momentary switch > flip flop > relay approach, but then was thinking this would be an excellent entry into coding the PIC. Sounds like the most straightforward thing would be to get a PIC with enough pins to do 1:1 input and ouput....which will be a lot of pins for a 8-10 loop bypass box....

nexekho

Is the PIC going to be doing anything special?  Like MIDI or something?  If you're adding a PIC for the sake of it, don't :p
I made the transistor angry.

swinginguitar

Quote from: nexekho on October 03, 2011, 10:53:01 AM
Is the PIC going to be doing anything special?  Like MIDI or something?  If you're adding a PIC for the sake of it, don't :p

If you consider my education something special, then yes, the PIC is doing something special :p

I am tempted to just go flip flop > relay route for the beta version, but the manic side of me wants to try PIC-ville!

Gurner

If you're pushed for pins, the less heartache is to go with a PIC with more pins! If you want heartache, then diodes as Molten voltage says is the way to go ...interrupts are the only way for me (I can't be done polling switches.....most of the time my main loop is busting it's gut anyway!) ....but the strategy when using diodes, is to ensure no matter which switch is pressed that the PIC's INT pin is 'triggered'...this generates an interrupt and then in the interrupt route your code then tests which switch pins are low ....from that it can work out which switch was pressed.

swinginguitar

#8
was also thinking i could use multiple smaller PICs - for example each group of 4 loops could be run by a PIC, then the next group another and so on.

Shouldn't be any problems with that approach huh?

What does the diode approach look like?

R.G.

Quote from: swinginguitar on October 03, 2011, 09:28:08 AM
R.G. - using your method, how are your pins configured - are they set to digital and are listening for a jump to/from logic hi/lo? Are you driving the LED directly from the output pin, or do you amp it up for extra current?
The trick is to make the pin digital, but flip it from being an output most of the time so it drives the LED, to being an input for a few microseconds to sense the switch. Both the pin and the switch pull the LED to ground (or V+). So when the pin lets go of the LED, if it's still pulled active, the switch is connected. It takes some fluffing about with resistors and caps to help filter out switch bounce and to prevent the switch from shorting the pin when/if the pin is trying to pull the LED the opposite way.

A PIC pin is fully capable of driving an LED on its own, no current amplification needed for single LEDs.
R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

potul

Hi,

I've been able to use 1 ADC input (10 bits) to monitor 6 switches, but it is not hassle-free, and I had to do some trial-error with the resistor ladder until the thing got stable. It is not as robust as I wish. Maybe using a resistor ladder IC with calibrated resistors would work better

Mat

R.G.

Quote from: potul on October 07, 2011, 03:48:32 AM
I've been able to use 1 ADC input (10 bits) to monitor 6 switches, but it is not hassle-free, and I had to do some trial-error with the resistor ladder until the thing got stable. It is not as robust as I wish. Maybe using a resistor ladder IC with calibrated resistors would work better
Probably better to spend your money on a CMOS latching input chip or on a PIC with more pins.

My experience with using analog inputs for digital levels is that you have to deliberately force the software to ensure broad dead zones between decision points, and sometimes use software hysteresis and/or time-line voting on inputs.
R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

nexekho

Quote from: R.G. on October 08, 2011, 02:28:47 PM
Quote from: potul on October 07, 2011, 03:48:32 AM
I've been able to use 1 ADC input (10 bits) to monitor 6 switches, but it is not hassle-free, and I had to do some trial-error with the resistor ladder until the thing got stable. It is not as robust as I wish. Maybe using a resistor ladder IC with calibrated resistors would work better
Probably better to spend your money on a CMOS latching input chip or on a PIC with more pins.

My experience with using analog inputs for digital levels is that you have to deliberately force the software to ensure broad dead zones between decision points, and sometimes use software hysteresis and/or time-line voting on inputs.

I found that when using dead zones, if I accidentally put the pot on the edge of one it would occasionally noise out over the edge, so I made it so you had to go half way through a sector of my pot to switch to it rather than using the exact boundary, so when it did switch you'd have to go a full sector back to go back.
I made the transistor angry.

R.G.

Yeah - it's never perfect. You then get into software hysteresis and time-line voting.

It is probably better to spend your money on CMOS latching input chips or a PIC with more pins.
R.G.

In response to the questions in the forum - PCB Layout for Musical Effects is available from The Book Patch. Search "PCB Layout" and it ought to appear.

ElectricDruid

My solution to the 'not enough pins' problem these days is to use shift registers. It's probably not worth it if you just need one or two more pins (for that, use a slightly bigger PIC - that's why they make so many) but the more pins you need, the more benefit you get. I use 74HC166 for inputs (add one chip for eight more inputs) and 74HC594 for outputs (same again). You need a data pin, a clock pin and a latch pin for each of those chips, but after that, you can keep sticking another chip on the end of the chain for as long as you like. Reading the data in or out is simple enough. You could use a serial interface, but I mostly write a bit banging routine to do it.

For switch debouncing (and I always debounce, even if I'm using switches attached to the shift registers) I use Scott Dattalo's vertical counter method:

http://www.dattalo.com/technical/software/pic/vertcnt.html

This takes a bit of reading to get your head around it, but it's a beautiful piece of coding. I've done it in ASM, in ASM30 for dsPIC, and in C. It's easy to implement in any of those, makes short code, and works perfectly.

Hope these ideas help,
Tom

tysonlt

Hey Tom,

Using shift registers is the method I plan to use. All the other methods sound scary.

Regarding bit-banging, is this how you do it?

In main loop:

1) send latch pin low
2) for each bit:
2.1) pulse clock pin
2.2) read input pin to buffer
3) send latch pin high

Repeat above for debouncing.

Sounds pretty easy. Would you mind please posting some code? In C maybe?? :)

I wonder if it can be done with interrupts?

ElectricDruid

Ok, here's a serial input routine from some recent code:


unsigned long SerialInput(void) {
// This reads 32 bits of data from the shift registers
   unsigned long data = 0;
   // First latch the data from the digital inputs into the shift reg
   SER_LATCH = 0;         // Take the latch low
   __builtin_nop();
   __builtin_nop();
   SER_CLOCK = 1;         // Send a clock pulse
   __builtin_nop();
   __builtin_nop();
   SER_CLOCK = 0;
   __builtin_nop();
   __builtin_nop();
   SER_LATCH = 1;         // Return latch to normal state
   __builtin_nop();
   __builtin_nop();
   // Now we've actually got the first bit of data on the output
   if (SER_DATA == 1) {
      data |= 0x80000000;   // Set highest bit
   }
   // Read the remaining bits of data
   int i;
   for (i=0; i<31; i++) {
      // Shift the old data down to give us space for the new bit
      data >>= 1;
      // Clock the data out of the shift reg
      SER_CLOCK = 1;
      __builtin_nop();
      __builtin_nop();
      __builtin_nop();
      __builtin_nop();
      SER_CLOCK = 0;
      __builtin_nop();
      __builtin_nop();
      __builtin_nop();
      __builtin_nop();
   
      // Read the data on the shift reg output
      if (SER_DATA == 1) {
         data |= 0x80000000;   // Set highest bit
      }
   }
   return data;
}


It's a bit long-winded because of all the __builtin_nop()s, which are just the C version of the assembly "NOP" (NO Operation) instruction which causes a one-clock delay. I was using a fast clock speed and needed to slow the routine down a bit. With (say) an 8MHz clock on a PIC, you probably wouldn't need them - check the datasheet for the serial chip you're using.

Also I never managed to get it to work putting all 32 bits inside the loop, though I don't really see why it shouldn't be possible. I finished up having to prime the loop before running it, as you see. But there's definitely room for improvement there.

Hope it helps - good luck!
Tom

tysonlt

Thanks Tom, that is perfect. It sg
Shows me how to actually pulse the clock which what I needed.

Understand re the clock pulses. I will probably use the PicPack library for boostc, it has some delay routines that adapt to the clock speed.

Thanks a bundle! :)