Good Arduino/C++ rotary encoder tutorial?

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
dfeldman
 
Posts: 29
Joined: Mon Jul 04, 2022 4:11 pm

Good Arduino/C++ rotary encoder tutorial?

Post by dfeldman »

Can anyone recommend a good Arduino / C++ beginner tutorial for rotary encoders? (I'm working with this one from Adafruit.)

I kinda half-get the idea of how it works but after a bunch of time poking at libraries, debouncing, sample code, etc., I'm still pretty far from actually getting it to work and was hoping for a nice step-by-step with both principles and sample code.

Thanks!

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: Good Arduino/C++ rotary encoder tutorial?

Post by dastels »

If you want to forego a library and learn the ins & outs of how the encoder works, see https://learn.adafruit.com/trinket-usb-volume-knob/code. There seems to be a C++ encoder library. See https://learn.adafruit.com/remote-effec ... the-remote for information.

Dave

User avatar
dfeldman
 
Posts: 29
Joined: Mon Jul 04, 2022 4:11 pm

Re: Good Arduino/C++ rotary encoder tutorial?

Post by dfeldman »

Awesome: the Encoder library referenced in your second example works like a charm.

In terms of avoiding a library via your first example, I had less luck, though I suspect this is due to my attempt to translate Trinket to ESP32 code. I've attached the original file for convenience and line-numbering. In particular:

(1) I wasn't 100% sure what purpose TRINKET_PINx served, and PINB isn't available on ESP32. It seemed like it was just using the Trinket to keep track of current position, so I removed the macro and replaced lines 37-43 with:

Code: Select all

  // read in the encoder state first
  if (digitalRead(PIN_ENCODER_A) == LOW) {
    enc_cur_pos |= (1 << 0);
  }
  if (digitalRead(PIN_ENCODER_B) == LOW) {
    enc_cur_pos |= (1 << 1);
  }
(2) And then I took a guess at a definition for bit_is_set() (again, not available on ESP32):

Code: Select all

bool bit_is_set(int val, int bit) {
  return val & 1 << bit;
}
(3) And replaced all the Trinket-related stuff at the bottom with:

Code: Select all

  if (enc_action > 0) {
    Serial.println("Up");
  }
  else if (enc_action < 0) {
    Serial.println("Down");
  }

The result compiles but mostly does nothing. If I aggressively turn the knob, sometimes I'll get an "Up" or "Down" output but kinda randomly and not related to the direction I'm turning.

So...I have a solution but would love to know what I'm doing wrong with the non-library approach, too.
Attachments
trinket-knob.txt
(2.76 KiB) Downloaded 3 times

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: Good Arduino/C++ rotary encoder tutorial?

Post by dastels »

There's "Trinket" terminology, but the logic isn't Trinket specific. The whole TrinketHID thing can be ignored. The idea is how the signals on the digital pins change relative to each other as the encoder rotates.

Your bit_is_set looks good.

Oh.. I see it now:

Code: Select all

  // note: for better performance, the code will now use
  // direct port access techniques
  // http://www.arduino.cc/en/Reference/PortManipulation
I hadn't caught that previously.

Good that you have it working!

Dave

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”