Multiple rotary encoders - Page 1
Forum section: electronics / projects

author: Greg Robinson
author_rank: Regular Contributor
timestamp: December 29, 2013, 05:29:38 am
content: Hi everyone,I recently asked a question about driving a large number of relays (operating as 8bit digital pots) from a microcontroller, and I received some great help, settling on using shift registers.Now my lack of experience with digital hardware is showing again.I would like to use 12 rotary encoders to control 12 digital pots (relay banks). I would also like two digit 7 segment displays to show the value each is set to. I'm hoping to use an Arduino Mega 2560 for the mcu.How would you recommend I accomplish something like this?Thanks again for any assistance, and the help I've received so far.

author: Greg Robinson
author_rank: Regular Contributor
timestamp: December 29, 2013, 08:03:06 am
content: Ok, so I think I've answered my own question about the 7 segment LED displays, I can use serial LED drivers (like theMAX7221) and only use 3 pins on the micro-controller.Still not sure how I can multiplex the rotary encoders though.

author: Rerouter
author_rank: Super Contributor
timestamp: December 29, 2013, 08:03:56 am
content: I really sounds like your not doing much processing wise, as you would only need to update the 7 seg each time the encoder changes,the relays and 7 segment can be be handled by some 74HC595's, below is a bit of code off an older project of mine the tri-stating bit can probably be cleared up, the idea was to write out to 2 of those chips in series using a hex value (memory card tester) but you can use it to write out your value directly.DO_SO = Serial Input to chipDO_OE = Output Enable PinSCLK = Shift In ClockLCLK = Latch ClockCode:void DataOut(unsigned long DATA) { // Shift out datadigitalWrite(DO_OE, LOW); // Enable Shift Register Outputsfor(int D=0; D<16; D++) { // One by one clock out 16 bitsif(bitRead(DATA,(15-D)) == 0) { digitalWrite(DO_SO,LOW); }else { digitalWrite(DO_SO,HIGH); }Clock(DO_SCLK); // Clock the shift Register}Clock(DO_LCLK); // Clock The latchdigitalWrite(DO_OE, HIGH); // Tristate shift register outputs}void Clock(int Pin) { // Rising Edge Clock FunctiondigitalWrite(Pin, LOW);digitalWrite(Pin, HIGH);}as for the 12 rotaries, each port (not pin) on the At mega has a pin change interrupt, so you can either burn 24 pins and do it very quickly by bit-reading all 24 pins on any change, or offload the second pin of every encoder to a 74hc165 shift register, taking note of a change on only 1 encoder pin.below i have attached my current encoder interrupt code (I'm only using a single encoder Model: ECW1J-B28-AC0024L) this is the software side of the denouncing, i also have a 10K resistor in series and a 1nF cap to ground (micro side of resistor) on each pin, with the pin lift up turned on, while i could likely improve the de-bouncing routine or hardware, like you I'm not really doing anything else when I'm changing a value.Code:void encoder() {if(millis() - LastMillis > 20) { // If less than 20ms has elapsed, ignoreif(bitRead(PINB,0) == 0 /*bitRead( PIND,3)*/) { // If encoder pin A and B read the samePos++; // spinning clockwise so increment,}else {Pos--; // otherwise spinning counter clockwise so decrement,}LastMillis = millis(); // Record last time to compare}}edit: a side thought, with 12 pins for encoders, 3 for your output shift registers, and 3 for your input shift registers you could manage it on a 328 with no free pins

author: Greg Robinson
author_rank: Regular Contributor
timestamp: December 29, 2013, 09:27:05 am
content: Thanks for the suggestions and code examples Rerouter!The parallel in serial out shift register for the rotary encoders is a great idea, seems so simple and intuitive once you've been told about it!Maybe I should give some more info on my project?The idea is a vacuum tube musical instrument amplifier, with 12 control parameters, using the digital pots to be able to select pre-set values using midi or other control input (also with the ability to save those pre-sets to EEPROM).Being a bit of an analog/linear purist led me to the 8 bit relay potentiometer concept - keep the audio signal path out of the digital domain, and away from potential distortion artefacts from fet based digital pots (not to mention the voltage limitations).There will also be a few other relay signal switching things to handle (I can just tack them on a shift register), so I'm trying to use as few pins as possible, ultimately hopefully allowing me to use a smaller micro-controller (a 328 would be perfect as it's available in a DIP package).So I'll need to reserve Rx and Tx for midi, 7 inputs for the 12 rotary encoders, 3 outputs for the digital pots, 3 outputs for the LED displays (maybe I should combine the pots and LED displays on the same shift register?), I guess I really want about 20 button inputs as well (guess I could use an analog in with an R-2R ladder, or another parallel in serial out shift register). I think a master LCD display is something I'm going to have to consider too. So, quickly running out of pins, but at least I'm not doing a whole lot of processing. Guess I should consider I/O expanders too, especially if I want to try and stick to through hole packages.Thanks again everyone!

author: Rerouter
author_rank: Super Contributor
timestamp: December 29, 2013, 10:03:27 am
content: Quote from: Greg Robinson on December 29, 2013, 09:27:05 amto do it right you need 12 inputs for the encoders, + the tie in for second group of 12 pins over the shift register, (3 pins min, Parallel load, clock and serial in) however you can string this input string as long as you like, by using bitread and bitset/bitclear commands for fixed pins, loading in this way can happen stupidly fast, so tie on any buttons you want, just do it after the encoders so that you only need to shift in 12 bits on an interrupt (be tidy)For your outputs do the same make the string as long as you like, you can clock things out very quickly, but equally take up at minimum 3 pins, (at 18 now, 2-13 + A0-A5, and you may want to share clocks as otherwise tying the output latch pin to clock will have your relays rattling along as the new setting gets shifted in.)so now how to get around the button dilemma, now you realistically could just read endlessly and add a small debounce loop like the encoder, or create a latch on the input, with my device as it can be very busy crunching other things for a few hundred milliseconds at a time i came up with the little 2 transistor latch in the image below, the switch on the left is your button, and the switch on the top is an output turning on or off a 20K pullup to 5V, with the result of the latch being the point called L, when the switch pulls the transistor low, it latches its output low, until its reset by removing the lift-up and re-applying it.as long as all your dealing with is logic inputs and outputs shift registers can be used, if you want to measure analog values, i2c port expanders might be the go, just know that i2c is much much slower than direct bit reads and writes.

author: Greg Robinson
author_rank: Regular Contributor
timestamp: December 29, 2013, 10:21:28 am
content: Quote from: Rerouter on December 29, 2013, 10:03:27 amWhoops! Yep, typo there.Thanks again for the assistance Rerouter, you've been a big help!

author: dannyf
author_rank: Super Contributor
timestamp: December 30, 2013, 02:46:53 pm
content: QuoteI would step back and think how insane that approach is. Not sure what you are trying to do but using 12 individual encoders to control 12 pots is just crazy, and difficult to implement on one mcu.Two options (out of many possible options):1) Use 1 encoder + 1 mcu to control 12 digital pots: fairly standard and easy to implement;2) Use 1 encoder + 1 mcu to control 1 digital pot: modular and easy to do;