Atmel external interrupt and rotary encoder - Page 1
Forum section: electronics / beginners

author: Zanshin
author_rank: Contributor
timestamp: November 14, 2018, 07:24:48 am
content: The Atmel microcontrollers that I am using have 2 external pins that can be used to wake the device upon pin change. I am already using one of these and thus have only one left available. I would like to connect a standard quadrature encoder so that the device wakes up when it is turned. But the encoder has two lines that can be either "high" or "low" (1 or 0) when the device is put to sleep. Turning the encoder will transition one of these two pins to the other state. This gives 4 possible states where the transition to another state is always done just one pin at a time.State0 00 11 01 1I cannot figure out how to electronically combine these two pins so that any state change will trigger a pin change and wake up the device. At first I thought I could combine some diodes and an OR gate and a NAND gate, but that didn't solve my issue for all 4 combinations and thus I'm posting my question here to see if there is an answer to what I assume is a basic electrical engineering problem.

author: t1d
author_rank: Super Contributor
timestamp: November 14, 2018, 10:23:02 am
content: Hmm??? Where did my reply go?Not my strongest area, but...Rotary encoders have, very often, a separate switch that is actuated, by pressing down on the stem. There is a separate set of pins, for the switch. Three for the RE and two, for the switch.Set the pin state low, as a matter of the go-to-sleep procedure. When the pin goes high, on a button press, wake up and switch over to the RE decoding function. Or, visa verse, high to low. Don't forget the pull-up, or pull-down, resistors.This means that the switch and the RE share the one controller pin. Add diodes, to prevent power getting to the wrong place.If you must go with turning the RE, just turn the stem several clicks, to make sure that the logic state changes... On any change, wake up the controller and switch over to the decoding function...Hope that gives you some ideas...

author: Yanayoei
author_rank: Newbie
timestamp: November 14, 2018, 10:32:36 am
content: Gusto ko talagang malaman kung paano i-scan ang site at karamihan sa mga impormasyon tungkol dito ay sapat na upang ipaliwanag?

author: t1d
author_rank: Super Contributor
timestamp: November 14, 2018, 10:40:22 am
content: Quote from: Yanayoei on November 14, 2018, 10:32:36 amTranslated on Google"I really want to know how to scan the site and most of the information about it is enough to explain?"I think this was posted to the wrong spot, maybe?

author: Peabody
author_rank: Super Contributor
timestamp: November 14, 2018, 02:45:16 pm
content: One possibility is to select an encoder which has the same number of detents per revolution as pulses per revolution. These will have both switches open at every detent, so any wakeup transition would always be high-to-low on one of the switches, and diodes could be used for the OR function. Of course the servicing algorithm for these encoders is slightly different than for those with pulses = detents/2. You get the full 11-10-00-01-11 or 11-01-00-10-11 sequence between each detent.Once your device wakes up, how are you planning to service the encoder? Will you be using polling?

author: MasterT
author_rank: Frequent Contributor
timestamp: November 14, 2018, 04:12:33 pm
content: On my atmega I'm using this library:http://www.mathertel.de/Arduino/RotaryEncoderLibrary.aspxThe trick is any digital pin could trigger interrupt, and library does decoding. Works very fast, better than any other libraries I tried.Code:Here is the implementation for the pin change interrupt in the case you have used the A2 and A3 lines for the encoder.Enable the Pin Change Interrupt 1 in general that covers the Analog input pins or Port C:PCICR |= (1 << PCIE1);Now enable the interrupt for pin 2 and 3 of Port C:PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);Now the Interrupt Service Routine only has to call the tick function:ISR(PCINT1_vect) {encoder.tick(); // just call tick() to check the state.}You can also find this in the InterruptRotator example.

author: Kasper
author_rank: Frequent Contributor
timestamp: November 14, 2018, 04:17:38 pm
content: Use the lower of the 2 bits, the one that changes every time to trigger the interrupt.If you have an extra io pin, connect the other bit to it and read it once mcu is woken up. If not then just base everything off counting the lower bit.And try to minimize the code in the interrupt.

author: Zanshin
author_rank: Contributor
timestamp: November 14, 2018, 04:31:17 pm
content: Thanks for the replies.I@t1dI am already multiplexing the pushbutton from the rotary along with some other pins to trigger a wakeup on the other Atmel hardware interrupt pin. That part is easy, since the state of each pin is known when the Atmel is put to sleep. Bit I also need to trigger the wake-up by an encoder rotation and the state of the two pins at "sleep time" is indeterminate. I can't just monitor one pin and wake up when that changes state, since if the other pin is "leading" then I would lose that rotation.@PeabodyI've already written a rotary encoder library in the past that uses interrupts (https://github.com/SV-Zanshin/RotaryEncoder) but now I'm putting a specific device together and really want to minimize energy consumption so am trying to leverage the 2 hardware I/O pins which can wake the Atmega chip up; if I kept the processor at a lesser level of sleep I could use pin change interrupts on my pins, but the power savings would be much less.@KasperIf I use just one pin I would lose one "tick" if the pin I am watching is not the leading one on the quadrature, and that isn't acceptable for this design. I always avoid excess code in interrupt, but in this case the interrupt is a wake-up one which just re-enables internal registers and is so quick that the standard interrupt handlerI have for the encoder can still register the pin change.@MasterTThanks for code post, but I'm already using similar code in my own library (see link above). Unfortunately many Atmega processors such as the ATMega168 or ATMega 328 only have 2 external interrupt pins that can wake the processor from deep sleep.But that does give me an idea that might work - if I attach the CW and CWW pins of the encoder to the 2 HW interrupt pins, and also add the output of the pushbutton pin (through a diode) to both pins then a turn or a click would cause one or both to trigger a wake-up.... Oh, but then a pushbutton event during normal processing would simulate an encoder turn... but perhaps I could disconnect that connection after the system wakes up... That does give me food for thought, thanks.I have a prototype working now for a small breakout board for the 3-color and 2-color LED encoders that is software configurable to output TTL-Serial, SPI, I2C and/or 1-Wire to a controlling processor - eliminating the need for writing code to control the LED and also eliminating having to reserve 6 pins for rotary encoder. The last part left is figuring out how to ensure a timely wake-up from sleep mode and then the prototype will be finished and ready to get miniaturized onto a PCB. If all works out well this might even be productized

author: Kasper
author_rank: Frequent Contributor
timestamp: November 14, 2018, 04:33:58 pm
content: If you only have that one pin and it has ADC, you could combine your 2 encoder outputs. Connect each to their own diode and different value resistors then connect those resistors together and go through another resistor to GND.That will create a voltage divider that gives different voltage at each of the 4 states. The tricky part will be to have the voltage in all but state '0 0' be high enough that it triggers the interrupt but spread out enough that ADC can clearly tell which state it is in.

author: Zanshin
author_rank: Contributor
timestamp: November 14, 2018, 04:46:28 pm
content: Kasper - sorry I missed your post before updating my original post. I think that it might work without those extra pieces of hardware, a single diode might suffice after all, plus a OR-Gate for the other pins.

author: Kasper
author_rank: Frequent Contributor
timestamp: November 14, 2018, 05:46:24 pm
content: Instead of a diode and an or gate maybe some FETs.

author: Dave
author_rank: Super Contributor
timestamp: November 14, 2018, 08:48:57 pm
content: An XOR will always change its output state regardless of which pin changes first.

author: Zanshin
author_rank: Contributor
timestamp: November 15, 2018, 07:18:06 am
content: Dave - thanks, I had neglected to think that a quadrature only changes one pin at a time and only though about the end state. With the 2 pins going through an XOR and the Atmel external interrupt hooked up to that I would get a pin-change event regardless of the initial state of the encoder pins and that would wake up the device. In addition, I'd only need that small XOR chip and wouldn't need to add a diode to the PCB. Plus it is a cheap solution at under $0.06 in bulk.

author: mvs
author_rank: Frequent Contributor
timestamp: November 15, 2018, 07:49:49 am
content: Quote from: Zanshin on November 14, 2018, 04:31:17 pmAtmega 168 and 328 have not only 2 External Interrupts (INT0, INT1), but also Pin Change Interrupts PCI0-PCI2 that are wired to all digital pins (PCINT0-PCINT23).

author: Kleinstein
author_rank: Super Contributor
timestamp: November 15, 2018, 08:06:53 am
content: If the encoder is for manual control (the push bottom suggests this) one could use just one of the lines for wake up. Depending on the way you look at the decoder one would loose some resolution and might get some rare glitches.The suitable logical function would be an xor to get a signal change on any movement. However the extra power consumption and pin count might be a problem.There are more interrupts via pin change interrupt. Another option is the ICP function - though it does not work with all power saving modes.

author: Naguissa
author_rank: Regular Contributor
timestamp: November 15, 2018, 08:11:27 am
content: You can use only one of both, as pulses come very close (you will need turn the encoder a little bit more) or use a xor gate and wake up on change if possible.Enviado desde mi Jolla mediante Tapatalk

author: Zanshin
author_rank: Contributor
timestamp: November 16, 2018, 06:36:04 am
content: @mvsThe Atmel is in power off mode, so only the 2 external interrupts or an I2C address match will wake it up; therefore I can't use the pin-change-interrupts on any other pins. The Rotary encoder uses pin-change interrupts in normal operating mode.I've got some 4-channel XOR chips on order now which fit perfectly - I have a total of 5 external lines which can trigger a wakeup (clockwise turn, counterclockwise turn, pushbutton, SPI SS and 1-Wire) so the XOR solution fits perfectly for this project: low-cost, low-energy and a small footprint.Thanks for all the help!

author: mvs
author_rank: Frequent Contributor
timestamp: November 16, 2018, 08:09:42 am
content: Quote from: Zanshin on November 16, 2018, 06:36:04 amPin Change Interrupt is a valid wake up source for all sleep modes including power down, see Table 7-1 in Atmega328P datasheet.

author: Zanshin
author_rank: Contributor
timestamp: November 18, 2018, 08:10:53 pm
content: @MVSwe were looking at the same datasheet but one of us was mis-interpreting the chartWhile I've now got some unnecessary XOR chips on order, I can now use the pins directly to wake up the Atmel; I'm already using pins from each of the pin-change-interrupt ports so I don't even have to change my code.Thanks.