multiple encoders

dear forum

in a project i am working on i want to connect 12 rotary encoders to the arduino board.
and my general question to you is how to achieve this the best.
i already found some stuf about d-flipflop's so that CW and CCW rotation are just pulses on 2 different inputs.
but my main concern is that because this project als needs to read other inputs, and needs to send on other outputs i will meaby miss a few pulses thus resulting in a none-reliable result.
a other thing i came up with is to use a giant OR-poort on a interupt iput
so that if aCW rotation or a CCW rotation is monitord it will trigger an interupt and then read out wich one of the encoders is sending pulses

I would very much like to hear your thought in this matter since i have never worked with interupts before

If the encoders will be running slow you could hook several up to and arduino - but only if they are running slow. For high speed you would need to use interrupts and then the problem becomes missed interrupts. You might consider using something like an ATtiny2313 and then communicating back to a master processor.

Encoders have an A and a B output. Tieing A to and interrupt pin and B to an input. On interrupt from A check B and if HIGH add 1 to PositionVar, if B is low Subtract 1 from PositionVar.

For higher speed encoders you may need to use assembly language (a little more difficult, but much faster, more responsibility on you and less on the compiler...)

going dual core on this project was something i really wanted to avoid.
but could the idea of using D-flipflops and a giant OR-port work ? pros and cons?

The ting with the D-flipflops is really similar to the ls7183 for clarification

12 Encoders make it difficult to do in one device. As mentioned, if the pulses are coming at 100 Hz or less then you can probably do it with one Arduino, but if you have 12 non-synchronous inputs at 1 KHz or more, It is likely you would miss pulses.

You could have several micros or Arduinos so that each one is only capturing the signal from 1 or 2 encoders and a master controller that consolidates the info and takes whatever action is needed.

You could make 12 counter circuit to either count the number of pulses in a fixed time or record the time between pulses, then the micro reads the counter values for all the signals and takes action.

You could look at 1 or 2 encoder signals at a time and rotate through all the signals if you can ignore the signals for some time without a problem.

We might be able to provide more guidance with more info about your application and what the signals look like.

If you're going to use logic ICs on each encoder anyway, why not just go with the suggestion to dedicate a ATtiny to each, and have your main controller just read the values via a serial bus? A Tiny can be had for much less than a dollar apiece. You may have some sense of pride from being able to stuff all this on one chip, but the practicality is that it will be ugly as sin and probably not work that well. The path of least resistance is calling you.. and we have cookies!

Are these mechanical encoders or optical encoders? Mechanical encoders are like push buttons. Use the right logic (grey code) and 10 pins will handle 12 encoders. If they are optical encoders, maybe it's difficult.

If you're going to use logic ICs on each encoder anyway, why not just go with the suggestion to dedicate a ATtiny to each, and have your main controller just read the values via a serial bus?

i took a look at this and this really seems like a good suggestion. its njot super expensive and very reliable. i would then program it that te main arduino would send a signal and then recieve the serial data at intervals (8-16 times a second) that sould do the trick. also is it simple to program a ATtuniy using the arduino or does that require me to reinstal avr studio and the whole shabang?

The path of least resistance is calling you.. and we have cookies!

Awsome!

Are these mechanical encoders or optical encoders? Mechanical encoders are like push buttons. Use the right logic (grey code) and 10 pins will handle 12 encoders. If they are optical encoders, maybe it's difficult.

i have mechanical encoders, could you ploease explain what you mean and why 10 pins are neededin stead of 24+vcc, you must keep in mind that i cannot read every signal switch over 12 encoders due to them sometimes spinning to fast for the arduino to read (only when you use multiple or when you have lots of other things going on taking up programm time.

Regarding my 10 pin conclusion, the encoders need to be connected like a matrix keypad and special code needs to be written to make sense out of the reading, but not all that impossible. Regard each encoder channel as one junction of a row and a column, then you can do 4 column by 6 rows so 24 total junctions for 12 encoders, each with 2 channels. I disagree with you that you can spin the encoder faster than Arduino can sense. You probably refer to a combination of poor programming skills and slow perceived speed of arduino due to the mentioned skills. You could directly use the keypads library to do this but you need to then couple the library result with grey code to make sense of what happened. The common of all encoders should be connected to gnd.

daatse:
is it simple to program a ATtuniy using the arduino or does that require me to reinstal avr studio and the whole shabang?

No need for the whole package. I haven't built a Tiny setup (no Tiny-sized projects just yet), but from what I've read around here, if you use one with good support you should be all set. Hardware wise (Arduino as ISP) you're fine.

My interest is piqued by the matrix setup. Might be worth trying that out first...

There are probably simple small ICs that can do the grey code for you so with two encoder channel inputs it gives two digital outputs each pulsing to indicate up or down rotation of the encoder. Encoder are very simple digital inputs so there's no reason that a matrix won't work. I just don't have many encoders to make a matrix out of them. If the OP doesn't need track two or more encoders being turned simultaneously, then this would be easier.

There are probably simple small ICs that can do the grey code for you so with two encoder channel inputs it gives two digital outputs each pulsing to indicate up or down rotation of the encoder.

i forgot to mention that i just have simple "2-channel" encoders, i beleive the term is quadruature. the first suggestion i made in the topic was about D-flip flops and if that was a solid idea. the suggestion you just made about the ic's do the same thing. the only problem (in my opinion) is that i might be difficult to catch al the pulses since my program must do a lot more besides reading encoders.

the encoders need to be connected like a matrix keypad and special code needs to be written to make sense out of the reading, but not all that impossible

this is a good suggestion and i think i will try to do this first with a 2x2 matrix. later this afternoon i will post a rough sketch of what the sketch should look like for you guys to evaluate. However making a 6x4 matrix or 2 2x6/3x4 matrixes (A and B channel sepparated) is not the problem, my main problem is that i'm going to implement multiple other things on this same arduino(mega 2560). wich will take up time for example a 8x8 button matrix and a (self made) driver for about 256 leds.

I disagree with you that you can spin the encoder faster than Arduino can sense. You probably refer to a combination of poor programming skills and slow perceived speed of arduino due to the mentioned skills.

i consider myself a pretty descend programmer and i dont think that my programming skills will cause any missed values. however when i have some sketches to show i will show u for feedback

edit:

i just have simple "2-channel" encoders, i beleive the term is quadruature.

"Incremental rotary encoder" is the correct term. and i have 22 detents on them

You can multiplex rotary encoders using external diodes. For 12 encoders I would use 2 pairs of input pins and 6 output pins, total 10 pins, plus 24 small signal diodes (e.g. 1N4148). If you are driving any other multiplexed devices such as LEDs or 7-segment displays, then you can share the output pins with these other devices.

You need to poll each encoders around every 2ms or faster to avoid missing transitions. I find this easiest to do by setting up a regular interrupt, for example by using the MsTimer2 library.

I have code for this, you can find it at the end of Five things I never use in Arduino projects | David Crocker's Solutions blog.

Okay i made a rough sketch of what the program wil look like
note: its not formatted and not checked in any way

/*
im using a shift register for the collom indication the last shit out is connected to data in of the same register
the encoder matrix is 12 encoders thus 24 pins thus a 6x4 matrix
4 Rows 6 Colloms
setup lik this

A1 A2 A3 A4 A5 A6 
B1 B2 B3 B4 B5 B6
A7 A8 A9 AA AB AC
B7 B8 B9 BA BB BC  (using letters so that the tabel stays neat)

*/


#define row1 = 		// inputs
#define row2 = 
#define row3 = 
#define row4 =
#define shiftpin =   //shift register output
#define shiftclck =   //shift register clk signal


Boolean Rotary_status[4][6];
int col = 1;
int Rotary_value[12];

Rotary_init(void){
_clR();
digitalWrite(shiftpin,HIGH);     // set the active row in the shift register
_CLK() 
digitalWrite(shiftpin,LOW);
for (col<= 6; col++;){                     //current value must be saved
Rotary_status[1][col]=digitalRead(row1);
Rotary_status[2][col]=digitalRead(row2);
Rotary_status[3][col]=digitalRead(row3);
Rotary_status[4][col]=digitalRead(row4);
_CLK;
}
col =1;
}

_CLR(void){
digitalWrite(shiftpin,LOW);
for (int i=0; i>=7;i++) _CLK();
}

_CLK(void){
//creates a pulse  on  pin shftclk this programming is not important for this sketch now
}


main loop(){
col=1;
for (col<= 6; col++;){ 
if (digitalRead(row1)!= Rotary status[1][col] || digitalRead(row2)!= Rotary status[2][col]){
rotary_event(col,1);
Rotary status[1][col]=digitalRead(row1);     //assign new values
Rotary status[2][col]=digitalRead(row2);
}

if (digitalRead(row3)!= Rotary status[3][col] || digitalRead(row4)!= Rotary status[4][col]){
rotary_event(col,2);
Rotary status[3][col]=digitalRead(row3);     //assign new values
Rotary status[4][col]=digitalRead(row4);
}
}

rotary_event(int A,int B){ // B is for rotary number clarification B*col=rotary value
/* some CW or CCW detection wich output+1 0 or -1 as variable C*/
Rotary_value[(A*B)]=Rotary_value[(A*B)]+C;
}

EDIT: i know thething with the shift register is not yet foolproof here but i will tackle that problem later on

My suggestion used 10 Arduino pins: 6 column output pins (possibly shared with other multiplexed devices), and 4 input pins (2 pairs of 2). If you are trying to reduce the pin count, then rather than use shift registers, I would use just 2 input pins and a 4-to-16 line decoder, such as a 74HC154. Total 6 Arduino pins. That will handle up to 16 encoders, or 10 encoders + 12 pushbuttons, etc. (note that many mechanical rotary encoders incorporate a pushbutton as well). You will need the diodes whatever hardware you use, because in some states all 3 pins of the encoder are connected together.

sorry about the wrong assumption of your programming skills. If your arduino is doing a very heavy main loop, you could try using timer1 library to periodically fire up a rotary encoder sense routine, like every 2 to 10 ms like dc42 suggested. In the routine you sense all inputs with your posted code and when there is a confirmed input, add it to a FIFO buffer for your main loop to process. This way you will not likely miss a beat (well, unless your main loop does some heavy hardware bus timing that disables interrupts). The sensing speed is not a problem. Then the response speed to user input is still bottle neck with a heavy loop. If you instead manipulate variables in the interrupt loop, you need to make sure there is no contention (or what you call it) when the main loop is seriously using that variable and interrupt fires up and changes it. Another solution is back to kf2qd, use one processor to process these and send back to master. That still won't solve the slow response processing in case of a heavy loop.

BTW, the comment of your code has some vulgar language. The #define needs to have no "=" signs. The rest looks good.

thanks dc42 and liudr for heklping me out

I would use just 2 input pins and a 4-to-16 line decoder, such as a 74HC154.

why not a 3-to 8 since i only have 6 collums to manage, and also one wihtout inverted outputs. but i get the suggenstion thx

note that many mechanical rotary encoders incorporate a pushbutton as well). You will need the diodes whatever hardware you use, because in some states all 3 pins of the encoder are connected together.

i indeed have encoders with pushbuttons, and also bought some diodes to prevent ghost buttons
these pushbuttons are going to be incorperated in a 8x8 button matrix. but could you explain why all 3 pins will be connected together in some states?

your arduino is doing a very heavy main loop, you could try using timer1 library to periodically fire up a rotary encoder sense routine, like every 2 to 10 ms like dc42 suggested.

i think it will do a heavy main loop and ofcourse im gonna do the timer regulation thingy,but not with interupts
a sidegoal of my project is that i will not use interupts to compleet it. Mainly because i always thought of interupts as somewhat unstable. i will however look past my sturdyness if thats the best way to go

add it to a FIFO buffer for your main loop to process. This way you will not likely miss a beat

why should using a FIFO buffer make it less likely to skip a beat? the buffer needs to be prossesed to so there it just takes up some memory,programming time and the encoder response time will be slightly larger

If you instead manipulate variables in the interrupt loop

in the code im not using any interupts yet "rotary_event" is just a crappy choise of words

Another solution is back to kf2qd, use one processor to process these and send back to master

i took a look at the ATtiny45, and made a backup plan for when the matrix does not meet my recuirments. buy 6 ATtiny's(every one controls 2 encoders) and use one serial port(2pins) on the arduino. name the A?ATtiny's A to F and when you need the new value Serial send A , then the ATtiny send back a signed int of how much and in what direction the encoders moved since the last serial checkup. Then reset the 'movement integer' in the ATtiny. but this was al just backup planning

in about a week my encoders will arive, ill keep you guys posted on any problems that will occur. Code that works, and what method i went with

daatse:
why not a 3-to 8 since i only have 6 collums to manage, and also one wihtout inverted outputs. but i get the suggenstion thx

Using 6 columns (3 output pins and a 3-to-8 decoder) and 12 encoders, you need 4 row inputs. If you use 12 columns instead (4 output pins and a 4-to-16 decoder), you need only 2 row inputs. You save an Arduino pin, and the code is simpler because all encoders use the same 2 row inputs.

daatse:
these pushbuttons are going to be incorperated in a 8x8 button matrix.

Why use a separate matrix for the pushbuttons, when you already have the column outputs? Simplest solution is to add a third row line for the pushbuttons. Each of the 12 column lines would drive one encoder and its pushbutton. You have 4 column lines spare, so you have capacity for another 4 * 3 = 12 ordinary pushbuttons. If you have even more pushbuttons (you mentioned an 8x8 matrix), just add more row lines.

daatse:
but could you explain why all 3 pins will be connected together in some states?

Quadrature encoders have a common pin and two quadrature pins. Contacts between the common pin and each of the quadrature pins make and break as you rotate the encoder. In some states, both contacts are made, therefore the 3 pins are connected together in those states. The pushbutton is independent, the encoder has 2 separate pins to connect it.