# Best way to emulate a rotary encoder wheel?

**URL:** <https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982>\
**Category:** Libraries\
**Created:** [June 18, 2020, 11:37pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982 "2020-06-18T23:37:36Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [June 18, 2020, 11:37pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/1 "2020-06-18T23:37:36Z")

</div>

Hello all. Trying to find the easiest way to capture user input on an encoder wheel. In theory, I would want to track the clockwise / counterclockwise mouse movement within the area representing the encoder. So instead of just moving a slider left to right or up and down, the user can actually rotate their mouse around a center point.

Thanks all!

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 19, 2020, 6:58am UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/2 "2020-06-19T06:58:50Z")

</div>

Please look at the GUI libraries

Such as G4P or controlP5

They should have this

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [June 19, 2020, 9:48pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/3 "2020-06-19T21:48:26Z")

</div>

I was hoping for a way without a Library - but I guess this does answer my question on the “easiest” way…

Edit: Also, neither of these libraries have the kind of “knob” or “encoder” I am trying to make.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 19, 2020, 9:53pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/4 "2020-06-19T21:53:12Z")

</div>

or something like this

> [@Creating sectors in a rotating circular image](https://discourse.processing.org/t/creating-sectors-in-a-rotating-circular-image/20781/):
>
> Hi, I have a circular image that rotates on mouseDragged and the image has various letters around the circle, when I drag the image to a certain position, one of the letters goes on top of a box indicating i want to write that letter, but I’m having problems coding this last part. I don’t know how to create and identify each sector of the image when in rotation. Any ideas?

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [June 19, 2020, 9:57pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/5 "2020-06-19T21:57:32Z")

</div>

I think this looks more promising!

Thank you!

---

<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:** [June 20, 2020, 4:23pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/6 "2020-06-20T16:23:20Z")

</div>

Hello,

Thanks for asking this! Had some fun with it…

Sharing my initial steps…

I did not look at other examples.

1. Create a PGraphic image. I used random circles but this could be your encoded wheel or anything.
2. Move the mouse over the canvas to detect colors.
3. Do something with the detected colors.
4. The rest is up to your creativity and imagination. I used the same concepts in the past to do something similar.

In my example the mouse location turned red or green depending on color it detected.  
You can leave the mouse location and rotate image with key ‘4’ and ‘6’.  
You can create a new image with key ‘5’.

Code is not commented so you can go through it.  
Ask if you have questions.

> **Example Code \< Expand this!**
>
> ```auto
> // Rotary Encoder 
> // v1.0.0
> // GLV 2020-06-20
> 
> // Step one to creating a rotary encoder simulation
> 
> PGraphics pg;
> color dot;
> float angle = 0;
> 
> void setup() 
> {
> size(400, 400);	
> pg = createGraphics(300, 300);
> ranCircles();
> }
> 
> void draw() 
> {
> background(255);
> push();
> translate(width/2, height/2);
> rotate(angle);
> imageMode(CENTER);
> image(pg, 0, 0);
> pop();	
> 
> int c = get(mouseX, mouseY);
>   
> if (c == color(0))
> {
> dot = color(0, 255, 0);
> }
> else
> {
> dot = color(255, 0, 0);  
> }
> noStroke();
> fill(dot);
> circle(mouseX, mouseY, 10);
> }
>   
> void keyPressed()
> {
> if (key == '5')
> ranCircles();
> if (key == '6')
> angle += TAU/100;
> if (key == '4')
> angle -= TAU/100;
> }
> 
> void ranCircles()
> {
> pg.beginDraw();
> pg.imageMode(CENTER);
> pg.background(color(255, 0));
> pg.noStroke();
> pg.fill(0);
> for(int i = 0; i<= 50; i++)
> {
> float theta = random(0, TAU);
> float r = random(0, 140);
> float x = r*cos(theta) + 150;
> float y = r*sin(theta) + 150;
> pg.circle(x, y, 20);
> }
> pg.endDraw();  
> }
> 
> ```

I took the code above, added a rotating arm and detected color at a point on the arm as it rotated.

screenX() and screenY() were used in place of mouseX and mouseY.  
Just be careful to detect color before you draw over the point you are detecting.

[https://processing.org/reference/screenX\_.html](https://processing.org/reference/screenX_.html)

`:)`

![rot01](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/897535ad3b685ee01be72f7c086893d9514b499d.gif)

I also used the image from the Wikipedia page directly:

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

See [https://processing.org/reference/PImage.html](https://processing.org/reference/PImage.html) to load and display images.

References:

> **[Rotary encoder](https://en.wikipedia.org/wiki/Rotary_encoder)**
>
> A rotary encoder, also called a shaft encoder, is an electro-mechanical device that converts the angular position or motion of a shaft or axle to analog or digital output signals.
> There are two main types of rotary encoder: absolute and incremental. The output of an absolute encoder indicates the current shaft position, making it an angle transducer. The output of an incremental encoder provides information about the motion of the shaft, which typically is processed elsewhere into information su...

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [June 20, 2020, 9:53pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/7 "2020-06-20T21:53:10Z")

</div>

> [@rkdnson](#):
>
> the user can actually rotate their mouse around a center point.

Do you want an absolute encoder, which gives an angular location value in some range (0-360) – or do you want an incremental encoder which produces an offset value (e.g. 0.1 or -0.05) each frame depending on how fast the mouse moved – and optionally sums those (so you could spin the dial on and on? Or something else – for example, an absolute encoder which rolls over to higher and higher numbers?

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [June 21, 2020, 11:24pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/8 "2020-06-21T23:24:47Z")

</div>

Wow! Thanks all, Im glad I checked back up on this. I will look at the code above - but to answer your question… I think an Incremental Encoder would be preferred!

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [June 23, 2020, 6:51pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/9 "2020-06-23T18:51:55Z")

</div>

> [@rkdnson](#):
>
> Incremental Encoder

This can be tricky for a few reasons –

1. PVector.angleBetween is unsigned
2. PVector.angleBetween doesn’t return the minimum arc
3. display components like arc() have similar behaviors – they are rooted and directed

Here is one example of a solution.

```auto
/**
 * IncrementalEncoderDemo
 * Jeremy Douglass 2020-06-23 - Processing 3.5.4
 * https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/7
 */
IncrementalEncoder ie;

void setup() {
  size(400, 400);
  ie = new IncrementalEncoder(width/2.0, height/2.0, 100);
}

void draw() {
  background(192);
  ie.update(pmouseX, pmouseY, mouseX, mouseY);
  ie.render();
}

class IncrementalEncoder {
  float val;
  float sum;
  PVector center;
  float size;
  float head;
  
  IncrementalEncoder(float w, float h, float size) {
    center = new PVector(w, h);
    this.size = size;
  }
  
  IncrementalEncoder(PVector center, float size) {
    this.center = center;
    this.size = size;
  }
  
  void update(float oldx, float oldy, float newx, float newy) {
    update(new PVector(oldx, oldy), new PVector(newx, newy));
  }

  void update(PVector pold, PVector pnew) {
    float angleOld = PVector.sub(pold, center).heading();
    float angleNew = PVector.sub(pnew, center).heading();
    head = angleNew;
    update(angleOld, angleNew);
  }

  private void update(float angleOld, float angleNew) {
    float diff = angleNew-angleOld;
    if (diff>PI) {
      diff = TWO_PI - diff;
    } else if (diff<-PI) {
      diff = TWO_PI + diff;
    }
    this.val = diff;
    this.sum += diff;
  }

  /**
   * Draw a rotary dial. An indicator points at the current position.
   * An arc highlights the active change and direction (red / blue).
   */
  void render() {
    pushMatrix();
    pushStyle();
    translate(center.x, center.y);
    rotate(head);
    line(0, 0, 50, 0);
    if (val<0) {
      line(0, 0, 50, 0);
      rotate(val);
      fill(color(0, 0, 255));
      arc(0, 0, 100, 100, 0, -val*3);
    }
    if (val>0) {
      fill(color(255, 0, 0));
      arc(0, 0, 100, 100, 0, val);
    }
    noFill();
    ellipse(0, 0, 100, 100);
    popMatrix();
    fill(0);
    textAlign(CENTER);
    text(val, center.x-size/2,center.y+size/2+10);
    text(sum, center.x+size/2,center.y+size/2+10);
    popStyle();
  }
}

```

Note that it is still hybrid – the knob has an absolute indicator line on it, which is absolutely oriented with “head” based on the last mouse position. If you wanted to make it a pure rotary encoder, it would be non-oriented – drop the head value and indicator line, drop the oriented display of difference with arc, make update(angleOld, angleNew) public, and don’t worry that the sum will drift from the orientation, because there is no orientation.

![Screen Shot 2020-06-23 at 11.50.42 AM](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/0b43e16789787b7db31827da02870d4f6492e8a5.png)

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [August 18, 2020, 5:57pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/10 "2020-08-18T17:57:06Z")

</div>

revisiting this. This solution is my current implementation, however I am finding that it is a little difficult to stop on a specific number. I tried using modulus on the sum to mimic a “tick”, and only outputting at 0. However, this doesn’t really work well.

Is there another way you could go about only outputting a “tick” every “x” degrees rotated?

Thanks!

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 18, 2020, 6:04pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/11 "2020-08-18T18:04:29Z")

</div>

When you say “a specific number” what kind of range and sensitivity are you looking for? Are you trying to dial between 0 and 10, or -100 and +100 – are these numbers integers? Do you want the knob to turn a quarter turn for a “tick”, or a tenth of a turn?

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [August 18, 2020, 6:25pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/12 "2020-08-18T18:25:11Z")

</div>

That i am not quite sure yet. I was hoping to try a couple different settings and see how it feels. My first gut feeling says somewhere between 5 and 15 degrees.

To clarify, the way I have this working looks like this:

```auto
if (diff > 0) { //CLOCKWISE
    encoderOutput = 1;
} else if (diff < 0) { //COUNTER-CLOCKWISE
    encoderOutput = -1;
} else {
    encoderOutput = 0;
}

//Listener event here

```

Where the listener event is simply sending which way the encoder is rotating for the OSC message.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 18, 2020, 6:27pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/13 "2020-08-18T18:27:49Z")

</div>

What is “diff”? Is that myEncoder.sum? Or is it `float diff = myEncoder.sum - previousSum` … ?

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [August 18, 2020, 6:29pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/14 "2020-08-18T18:29:24Z")

</div>

> [@jeremydouglass](#):
>
> ```auto
> private void update(float angleOld, float angleNew) {
> float diff = angleNew-angleOld;
> if (diff>PI) {
> diff = TWO_PI - diff;
> } else if (diff<-PI) {
> diff = TWO_PI + diff;
> }
> 
> ```

and then under that my code:

```auto
if (diff > 0) { //CLOCKWISE
    encoderOutput = 1;
} else if (diff < 0) { //COUNTER-CLOCKWISE
    encoderOutput = -1;
} else {
    encoderOutput = 0;
}

//Listener event here

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 18, 2020, 6:30pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/15 "2020-08-18T18:30:35Z")

</div>

Okay, so you are generating an OSC event anytime the wheel turns CW or CCW, no matter how little. But you want a minimum mount of turn before sending an event. Is that right?

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [August 18, 2020, 6:31pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/16 "2020-08-18T18:31:49Z")

</div>

Indeed! Sorry if I wasn’t great at making that clear!

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 18, 2020, 6:33pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/17 "2020-08-18T18:33:10Z")

</div>

And the events you send – are they just “+1” or “-1” events, or do they contain the myencoder.val or the myencoder.sum value?

---

<div class="post-metadata">

**Author:** ![rkdnson](https://avatars.discourse-cdn.com/v4/letter/r/cc9497/32.png) [@rkdnson](https://discourse.processing.org/u/rkdnson)\
**Post date:** [August 18, 2020, 6:33pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/18 "2020-08-18T18:33:47Z")

</div>

They are simply +1 and -1.

---

<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:** [August 18, 2020, 6:38pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/19 "2020-08-18T18:38:49Z")

</div>

> [@rkdnson](#):
>
> This solution is my current implementation, however I am finding that it is a little difficult to stop on a specific number.

A nice example was provided for you! Thanks @jeremydouglass.

I tinkered with his solution and was able to get this to work with 1 deg steps simply by:

- Convert heading to degrees
- Cast that to an integer
- Convert degrees to radians
- Use that as heading.

It was not a big leap to do this for any increment using the map() function.

I am getting nice steps moving around arm around with mouse.

This was just an exploration for me.

I will not be sharing code.

`:)`

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 18, 2020, 6:41pm UTC](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982/20 "2020-08-18T18:41:27Z")

</div>

Another way of approaching this problem is to create a Ticker class and feed the raw IncrementalEncoder values into it.

```auto
class Ticker {
  float pos;
  float lastTick;
  float step;
  
  Ticker(float start, float step) {
    this.pos = start;
    this.lastTick = start;
    this.step = step;
  }
  
  int update(int newpos) {

    // updates pos with newpos
    // and updates lastTick if there has been a tick;
    // returns 0, -1, or 1

  }
}

```

Now add a Ticker to the example sketch above, and call `myTicker.update(ie.sum);` in draw. If the call returns a 1 or -1, send that via your Listener.

One subtle difference is that @glv’s suggestion to scale the output e.g. with map also needs a past comparison value in order to trigger events, but it will stay oriented – the click position will never drift. The Ticker class I suggested you is accumulating floats, so it will slowly drift over time – the knob indicator won’t always click at exactly the same angle after a long period of use. That may not matter to you, but if it does then you might want to extend the IncrementalEncoder class and add the mapping function directly to it.

[Next page](https://discourse.processing.org/t/best-way-to-emulate-a-rotary-encoder-wheel/21982.md?page=2)
