# Handling rotary encoder signals

**URL:** <https://discourse.processing.org/t/handling-rotary-encoder-signals/14283>\
**Category:** Processing for Pi\
**Created:** [September 29, 2019, 4:09pm UTC](https://discourse.processing.org/t/handling-rotary-encoder-signals/14283 "2019-09-29T16:09:01Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![isdn](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/isdn/32/6611_2.png) [@isdn](https://discourse.processing.org/u/isdn)\
**Post date:** [September 29, 2019, 4:09pm UTC](https://discourse.processing.org/t/handling-rotary-encoder-signals/14283/1 "2019-09-29T16:09:01Z")

</div>

I’m working on a project that uses [this rotary encoder](https://www.adafruit.com/product/377) to control an onscreen element. I believe I understand how rotary encoders work in that there are two pins (A & B) that produce high or low pulses based on the direction of rotation and this rotation can be used to, for example, increment or decrement a counter based on the direction and amount of rotation.

I’ve adapted [this guide](https://dronebotworkshop.com/rotary-encoders-arduino/) to Processing and it works fine as long as I’m turning the encoder slowly, however if I do a quick turn the numbers seem to change almost at random (though the tend to - on the whole - decrement.) I’m new to physical computing but my instinct is that the signals are changing faster than processing is able to register them but I’m not quite sure how to route this problem or if my current approach is even correct.

This is for an art piece so I don’t care about exact measurement, directional changes would be fine. Code below and any suggestions really appreciated 🙂

```auto
import processing.io.*;

// Variables to track pulse states
int currentA;
int previousA;
int currentB;
int counter = 0;

void setup() {
  // pinA setup
  GPIO.pinMode(22, GPIO.INPUT_PULLUP);
  previousA = GPIO.digitalRead(22);

  // pinB setup
  GPIO.pinMode(27, GPIO.INPUT_PULLUP);
}

void draw() {
  currentA = GPIO.digitalRead(22);  
  currentB = GPIO.digitalRead(27);
  
  // has the A pin changed?
  if (currentA != previousA) {
    // if it has is it different than the value of pinB?
    if (currentA != currentB) {
      // if so we're turning clockwise
      counter++;
    } else {
      // otherwise we're turning counterclockwish
      counter--;
    }    
  } 
  
  // set previousA to currentA
  previousA = currentA;

  println(counter);
}

```

Thanks!

---

<div class="post-metadata">

**Author:** ![benja](https://avatars.discourse-cdn.com/v4/letter/b/fbc32d/32.png) [@benja](https://discourse.processing.org/u/benja)\
**Post date:** [September 30, 2019, 12:28pm UTC](https://discourse.processing.org/t/handling-rotary-encoder-signals/14283/2 "2019-09-30T12:28:50Z")

</div>

Hey,

actually this is normal behaviour of a rotary encoder. If you read the state of the pins once per frame, then you will most likeliy miss some changes. I never used GPIO before, just arduino. There you would use interrupts, to execute a function whenever the state of the pin changes. I guess it’s worth a try to look into [attachInterrupt()](https://processing.org/reference/libraries/io/GPIO_attachInterrupt_.html)

Regards.

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [September 30, 2019, 1:07pm UTC](https://discourse.processing.org/t/handling-rotary-encoder-signals/14283/3 "2019-09-30T13:07:59Z")

</div>

Hello!

This topic got me interested in this!

I have never used the RPI (Raspberry Pi) for GPIO interfacing; it always seemed unjustifiable to me for some implementations and always used a microcontroller (Arduino or otherwise) and serial port (or otherwise) to transfer data when needed. It has its place for other tasks.

The 3.3V was also something to deal with but no longer an issue for me.  
I have lots of these:

> **[Pololu - Logic Level Shifter, 4-Channel, Bidirectional](https://www.pololu.com/product/2595)**
>
> This tiny logic level shifter features four bi-directional channels, allowing for safe and easy communication between devices operating at different logic levels. It can convert signals as low as 1.5 V to as high as 18 V and vice versa,...

  
And there are other solutions to this as well.

However…

This topic got me interested and I will explore this further.  
[https://processing.org/reference/libraries/io/index.html](https://processing.org/reference/libraries/io/index.html)

Processing is not mentioned here:  
[https://www.raspberrypi.org/documentation/usage/gpio/](https://www.raspberrypi.org/documentation/usage/gpio/)

Is this library stable?

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/472522857006ccf50678e1c15e8fa1dc8ad44c30.png)

🙂

I tried this on PC to see what would happen and got an expected message:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/dff1818c1d2be0dc9bd457439ee8ed7e0a0b1886.png)

---

<div class="post-metadata">

**Author:** ![isdn](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/isdn/32/6611_2.png) [@isdn](https://discourse.processing.org/u/isdn)\
**Post date:** [October 1, 2019, 12:55am UTC](https://discourse.processing.org/t/handling-rotary-encoder-signals/14283/4 "2019-10-01T00:55:45Z")

</div>

@benja - thanks! `attachInterrupt()` did it and resulted in much cleaner code. I can tell I’m still missing some signals but more than good enough for my purpose.

@glv - I’m new to this put have been using the `Hardware I/O` library for a bunch of little prototypes and it has been working well for me. Making art in processing that is controlled by physical buttons and as long as the timing doesn’t need to be strict the results are pretty good. With a little touchscreen you can make some fun stuff.

For posterity here’s a working implementation of a rotary encoder in processing:

```auto
import processing.io.*;

int currentCLK;
int currentDT;
int counter;

void setup() {
  // DT setup
  GPIO.pinMode(27, GPIO.INPUT_PULLUP);
 
  // CLK setup
  GPIO.pinMode(22, GPIO.INPUT_PULLUP);
  GPIO.attachInterrupt(22, this, "clkChange", GPIO.CHANGE);
}

void draw() {
  background(0);        
  textSize(32);
  text("counter: " + counter, 140, 100);
}

void clkChange(int pin){
  if (GPIO.digitalRead(27) != GPIO.digitalRead(22)) {
    counter++;
  } else {
    counter--;
  }    
}

```
