Pages: [1] 2   Go Down
Author Topic: multiple encoders  (Read 2270 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

South Texas
Offline Offline
Edison Member
*
Karma: 8
Posts: 1025
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 124
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Anchorage, AK
Offline Offline
Edison Member
*
Karma: 42
Posts: 1176
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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?
Quote
The path of least resistance is calling you.. and we have cookies!
Awsome!
Quote
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.
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Anchorage, AK
Offline Offline
Edison Member
*
Karma: 42
Posts: 1176
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Quote
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.
Quote
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:
Quote
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
« Last Edit: May 15, 2012, 02:33:18 am by daatse » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6639
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 http://miscsolutions.wordpress.com/2011/10/16/five-things-i-never-use-in-arduino-projects/.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
/*
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
« Last Edit: May 15, 2012, 09:43:06 am by daatse » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6639
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Pages: [1] 2   Go Up
Jump to: