Offline
Newbie
Karma: 0
Posts: 33
|
 |
« on: May 10, 2012, 08:57:48 am » |
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
God Member
Karma: 8
Posts: 976
|
 |
« Reply #1 on: May 10, 2012, 09:31:25 am » |
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
Newbie
Karma: 0
Posts: 33
|
 |
« Reply #2 on: May 10, 2012, 09:50:22 am » |
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
Full Member
Karma: 0
Posts: 126
|
 |
« Reply #3 on: May 10, 2012, 09:59:45 am » |
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
Sr. Member
Karma: 10
Posts: 487
|
 |
« Reply #4 on: May 10, 2012, 02:28:43 pm » |
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
Faraday Member
Karma: 35
Posts: 5920
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #5 on: May 10, 2012, 10:05:27 pm » |
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
Newbie
Karma: 0
Posts: 33
|
 |
« Reply #6 on: May 14, 2012, 02:45:54 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Central MN, USA
Offline
Faraday Member
Karma: 35
Posts: 5920
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #7 on: May 14, 2012, 03:04:13 pm » |
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
Sr. Member
Karma: 10
Posts: 487
|
 |
« Reply #8 on: May 14, 2012, 07:58:52 pm » |
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
Faraday Member
Karma: 35
Posts: 5920
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #9 on: May 14, 2012, 09:38:53 pm » |
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
Newbie
Karma: 0
Posts: 33
|
 |
« Reply #10 on: May 15, 2012, 02:27:35 am » |
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
|
|
|
|
« Last Edit: May 15, 2012, 02:33:18 am by daatse »
|
Logged
|
|
|
|
|
United Kingdom
Offline
Faraday Member
Karma: 131
Posts: 4674
|
 |
« Reply #11 on: May 15, 2012, 02:47:22 am » |
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. http://www.eschertech.com
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 33
|
 |
« Reply #12 on: May 15, 2012, 09:41:13 am » |
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
|
|
|
|
« Last Edit: May 15, 2012, 09:43:06 am by daatse »
|
Logged
|
|
|
|
|
United Kingdom
Offline
Faraday Member
Karma: 131
Posts: 4674
|
 |
« Reply #13 on: May 15, 2012, 12:05:59 pm » |
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. http://www.eschertech.com
|
|
|
|
Central MN, USA
Offline
Faraday Member
Karma: 35
Posts: 5920
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #14 on: May 15, 2012, 02:14:38 pm » |
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
|
|
|
|
|
|