Morgan Olsson (morgans.rt at TELIA.COM) says
One pin only (!) low component count solution!! - And fast, and cheap, and failure detecting, possible to use only two wires (incl power and ground) to a panel daughterboard, and... ...an I think it will work, too... ;)Components: 1 IC, 1 diode (might be eliminated), 1 cap, 1-4 resistors (depending on how good you want it) For phantom feeding (true 2-wire incl power and GND): 1 tantalum cap, 1 1N4148.
The solution is based on a HC4017. It is a 5-stage Johnson counter with decoder, giving ten outputs "Qx" where x=0..9, one high at at time counting 0..9, (wrapping), and also a carry output "Cout" high during counts 0..4, giving us a total 11 outputs to play with.
CIRQUIT
- Connect each output from 4017, Q0 to Q9 and Cout, to one each position (1..11) on the rotary switch. Connect the reminding position (12) to Vss.
- Connect the rotor through a 10k resistor to the PIC pin.
- Connect the same PIC pin directly to 4017 "-ClockEnable", and tie 4017 Clock high. (this will make 4017 to advance on falling edge)
- Still from the only PIC pin, connect a resistor of 100k to 4017 Reset, and from there to Vss a cap of 10n. Parallel the resistor with a 1N4148 diode, cathode to PIC. For less EMI and nicer design I recommend a resistor in series with the diode, 220R to 1k depending of if you want to use the pin for other purposes / want fast discharge, or use ICSP on that pin.
ADDITION:
To detect error when the rotor has no contact with any position: If possible, enable pullup on the PIC pin, else you need to connect a separate pullup resistor (10k?), preferrable directly from the rotor to Vdd. This will always pull the PIC input high when set as input.
PROGRAM ROUTINE:
- Initialize:
- Keep the pin a output high during execution of your other routines. This will reset the 4017. Calculate the C and R time on 4017 reset pin accordingly. Also keep in mind that during execution
- Prepare:
- Set the pin low, and wait for the C to discharge throught the diode, and its resistor to bring the 4017 safely out of reset, with margin. (a few µs)
- Read:
- (Read the switch and advance the 4017)
- Tristate the pin. The output will remain low or rise depending on to which position the rotary switch is. No worry about clocking the 4017; we have set it to advance in *falling* edge. :)
- Write high to PIC output latch for later use
- Wait a few µs for input to stabilize ("goto $+1" make a one instr 2 cycle delay). Maybe use longer time, if using pullup to detect open connection error.
- Read the pin.
- Set the pin as output, (we did set the latch high earlier)
- then set it low. This will clock the 4017 (falling edge). This should be done ASAP, to avoid unneccessarily rising the reset cap voltage by keeping the pin low as much as possible, therefor processing the input after this:
- Store the read value for later use with table lookup (see below) (i.e shift into 2 registers)
Execute the read 10 times. The last time execute only paragraph 1..5, leaving the output high, eventually resetting the 4017 until next time.
- Decode: Now just look up in the table below to decode :)
TRUTH TABLE: ============ Position Pin Stored readings 1 Q0 HLLLLLLLLL 2 Q1 LHLLLLLLLL 3 Q2 LLHLLLLLLL 4 Q3 LLLHLLLLLL 5 Q4 LLLLHLLLLL 6 Q5 LLLLLHLLLL 7 Q6 LLLLLLHLLL 8 Q7 LLLLLLLHLL 9 Q8 LLLLLLLLHL 10 Q9 LLLLLLLLLH 11 Cout HHHHHLLLLL 12 Vss LLLLLLLLLL Open None HHHHHHHHHH (error detection, if pullup added as described above)The open condition may also occour during movement. Any other input data indicate movement, noise, or error.
NOTES:
- The PIC pins can depending on your other needs be chared with other output functions, i.e short clock or latch pulses (just the pin it is low for enough time to pull 4017 to reset). So... It might be that this rotary switch reader end up using NO extra PIC pin :)
- If interrupts need to be enabled during execution of this routine, have them enabled only when PIC pin is low. (A long time interrupt during pin high would reset the 4017)
- The diode and its series resistor might be eliminated if the "prepare" (getting 4017 reset low) proceeds during as long time as the "initialize", i.e holding pin constant during execution of other routines.
- If you can´t buy the 74HC4017, try the CMOS 4017, but then increase all resistors by a factor of about five, and run it five times slower.
- Hmmm... Instead of a rotary switch, Using diodes in series with the 4017 Q outputs could make it read buttons or other things. A one-PIC-pin keyboard! Using diodes between more than one output of the 4017 and a larger switch make it possible for i.e 20pole rotary switch (whatever use it has) Ok, diodes make the component count go up, but still only one pin from PIC, and one signal wire to the panel.
- To run the panel on only two wires: put all components in the panel, add a tantalum cap across the 4017 Vdd-Vss, and use a 1N4148 or BAT42 to feed power from the signal line (PIC pin) to the 4017 Vdd. Then only the signal line and Vss are required!
DISCLAIMER:
- I´m tired; might be thingking or writing erroneousky...
- Check component values, especailly if using PIC internal pullup
- Check reset timing R and C.
- If long wires, there might be problem with ringing affecting 4017 clock, then decouple it using a R and small C in series to Vss.
Untested, but I see no problems.
Enjoy !
PS Please tell me when/how it works for anyone who tries it out.
-I wanna know! DS
James Newton says:
Try 12 same value resistors, and a cap. Two pins, one to feed the resistor array, and one to read the cap voltage (just a CMOS input, not A/D) Take both pins to output, low for a short time. Take the cap pin to input, no pullup, start counting time Take the resistor pin to output high. When the cap pin reads high, stop counting. The time value will tell you how many resistors are in series.P1----R1-+-R2-+-R3-+.......R12-+ The switch connects one of the + symbols to P2 P2-------------------------+ Cap _|_ / / /If you have the time/inclination add another R in between P2 and the cap, and use the discharge time to facator out the cap value/tolerance. Discharge time = RC, and charge time = NRC, so NRC/RC = N, which is the number of resistors switched into circuit, and therefore the switch position.
If you want to do it digital, a pair of HC164 shift registers will let you shift a bit till you see it on the input, with the switch selecting which SR output is looked at. Literally N clocks = switch position.