Skip to content

Commit 770833f

Browse files
committed
update code and doc for rotary encoders examples
1 parent f9896df commit 770833f

File tree

6 files changed

+72
-35
lines changed

6 files changed

+72
-35
lines changed

Test-rotary-encoder-MIDI/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@ The code requires 3 libraries:
1515

1616
### MIDI_CONTROLLER
1717

18-
This library makes it really easy to create MIDI controls from buttons, switches, potentiometers, faders, sensors, rotary encoders... The only step required is to create your control, apply some settings to it and the library will take care of detecting and sending commands to the computer. That library also makes the Arduino Leonardo (and other compatible boards) to be detected as a MIDI device on your computer. [See full documentation](https://github.com/tttapa/MIDI_controller/wiki/Library-documentation)
18+
This library makes it really easy to create MIDI controls from buttons, switches, potentiometers, faders, sensors, rotary encoders... The only step required is to create your control, apply some settings to it and the library will take care of detecting and sending commands to the computer. That library also makes the Arduino Leonardo (and other compatible boards) to be detected as a MIDI device on your computer. [See full documentation](https://github.com/tttapa/MIDI_controller/wiki/Library-documentation).
19+
20+
As you can see in the code, we almost do nothing for the rotary encoder to work, no change detection, no debouncing, the library does everything for us. 👍
21+
22+
My goal was to use this control in Lightroom, via [MIDI2LR](https://github.com/rsjaffe/MIDI2LR). MIDI2LR will need a specific setting for a rotary encoder to work properly, see the comment in the code file.

Test-rotary-encoder-MIDI/Test-rotary-encoder-MIDI.ino

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
/*
88
This is an example of the "RotaryEncoder" class of the MIDI_controller library.
9-
Connect the A and B pins of the encoder to 2 interrupt pins (2 and 3).
9+
Connect the A and B pins of the encoder to 2 interrupt pins (0 and 1).
1010
It's recommended to use 100nF capacitors between the A and B pins and ground (hardware debounce).
1111
Connect the common (C) pin to the ground. Pull-up resistors are not necessary, since the internal ones will be used.
1212
Map the control change message 0x14 to the right control in your DJ or DAW software,
@@ -36,7 +36,8 @@ const uint8_t Channel = 1; // MIDI channel 1
3636
const uint8_t Controller = 0x14; // MIDI Control Change controller number https://www.midi.org/specifications/item/table-3-control-change-messages-data-bytes-2
3737
const int speedMultiply = 1; // No change in speed of the encoder (number of steps is multiplied by 1)
3838

39-
RotaryEncoder encoder(1, 0, Controller, Channel, speedMultiply, NORMAL_ENCODER, TWOS_COMPLEMENT);
39+
// If the control is reversed, inverse the 2 pins 0 and 1 here or directly on your board
40+
RotaryEncoder encoder(0, 1, Controller, Channel, speedMultiply, NORMAL_ENCODER, TWOS_COMPLEMENT);
4041

4142
// Instantiate a MIDI interface that sends debug messages to the USB Serial port (Serial Monitor)
4243
//USBDebugMIDI_Interface midiInterface(115200);

Test-rotary-encoder-volume/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ The encoder library allows us to easily interact with the encoder, without any h
2020

2121
Project-HID allows us to make the Arduino Leonardo appear as a *consumer* USB product on a computer, which is the only way to control volume on Windows machine (and probably OSX too). See [the documentation](https://github.com/NicoHood/HID/wiki/Consumer-API) for more information about `Consumer`. The library has some pre-defined constants for common USB codes, but you can send pretty much everything you want.
2222

23-
For more information about *consumer* USB codes, check the official USB documentation on HID usage tables[https://www.usb.org/document-library/hid-usage-tables-112](https://www.usb.org/document-library/hid-usage-tables-112). Codes for *consumer* hardware are on page 75).
23+
For more information about *consumer* USB codes, check the official USB documentation on HID usage tables [https://www.usb.org/document-library/hid-usage-tables-112](https://www.usb.org/document-library/hid-usage-tables-112). Codes for *consumer* hardware are on page 75).

Test-rotary-encoder-volume/Test-rotary-encoder-volume.ino

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,19 @@
88
// Might cause problems if other libs or code uses attachInterrupt()
99
#define ENCODER_OPTIMIZE_INTERRUPTS
1010

11+
// If the control is reversed, inverse the 2 pins here or directly on your board
1112
Encoder encoder(0, 1);
1213

13-
long encod = 0;
14-
const int step = 2;
14+
const int debounceDelay = 20;
15+
16+
long encoderCurrentValue;
17+
long encoderLastChange = 0;
18+
// The step allows us to change the "sensibility" of the encoder, we "detect" a change only if the encoder has changed n steps
19+
// The more steps, the least sensible
20+
const int step = 1;
21+
22+
long currentTime;
23+
long encoderNewValue;
1524

1625
void setup() {
1726
Serial.begin(9600);
@@ -20,19 +29,21 @@ void setup() {
2029
}
2130

2231
void loop() {
23-
long newEnc;
24-
25-
newEnc = encoder.read();
26-
if ( abs((encod - newEnc)) == step ) {
27-
28-
// Control sound?
29-
if (encod < newEnc) {
30-
Consumer.write(MEDIA_VOLUME_UP);
31-
} else {
32-
Consumer.write(MEDIA_VOLUME_DOWN);
32+
currentTime = millis();
33+
34+
encoderNewValue = encoder.read();
35+
if ( abs((encoderCurrentValue - encoderNewValue)) >= step ) {
36+
37+
if (currentTime - encoderLastChange > debounceDelay) {
38+
if (encoderCurrentValue < encoderNewValue) {
39+
Consumer.write(MEDIA_VOLUME_UP);
40+
Serial.println("Volume Up");
41+
} else {
42+
Consumer.write(MEDIA_VOLUME_DOWN);
43+
Serial.println("Volume Down");
44+
}
45+
encoderCurrentValue = encoderNewValue;
46+
encoderLastChange = currentTime;
3347
}
34-
encod = newEnc;
35-
Serial.println(newEnc);
36-
delay(20);
3748
}
3849
}

Test-rotary-encoder/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ If you don't know what a rotary encoder is, the official Arduino playground has
1111
The code requires 1 library:
1212
* encoder [https://www.pjrc.com/teensy/td_libs_Encoder.html](https://www.pjrc.com/teensy/td_libs_Encoder.html)
1313

14+
The code contains comments that should allow you to understand everything. If you're curious about *debouncing*, check [the official Arduino debounce documentation](https://www.arduino.cc/en/Tutorial/Debounce).
15+
1416
### Encoder
1517

16-
The encoder library allows us to easily interact with the encoder, without any hassle.
18+
The encoder library allows us to easily interact with the encoder, without any hassle.

Test-rotary-encoder/Test-rotary-encoder.ino

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,47 @@
55
// Might cause problems if other libs or code uses attachInterrupt()
66
#define ENCODER_OPTIMIZE_INTERRUPTS
77

8-
Encoder encoder(1, 0);
8+
// If the control is reversed, inverse the 2 pins here or directly on your board
9+
Encoder encoder(0, 1);
910

10-
long encod;
11-
const int step = 2;
11+
const int debounceDelay = 20;
12+
13+
long encoderCurrentValue;
14+
long encoderLastChange = 0;
15+
// The step allows us to change the "sensibility" of the encoder, we "detect" a change only if the encoder has changed n steps
16+
// The more steps, the least sensible
17+
const int step = 1;
18+
19+
long currentTime;
20+
long encoderNewValue;
1221

1322
void setup() {
1423
Serial.begin(9600);
1524
}
1625

1726
void loop() {
18-
long newEnc;
19-
20-
newEnc = encoder.read();
21-
if ( abs((encod - newEnc)) == step ) {
22-
23-
if (encod < newEnc) {
24-
// Going up
25-
} else {
26-
// Going down
27+
currentTime = millis();
28+
29+
encoderNewValue = encoder.read();
30+
if ( abs((encoderCurrentValue - encoderNewValue)) >= step ) {
31+
// Debouncing: consider a change of state is valid if it happens after x milliseconds
32+
// If not, we consider it as noise and do nothing
33+
if (currentTime - encoderLastChange > debounceDelay) {
34+
if (encoderCurrentValue < encoderNewValue) {
35+
// Going up
36+
} else {
37+
// Going down
38+
}
39+
Serial.print("Time: ");
40+
Serial.print(currentTime);
41+
Serial.print("; Last time: ");
42+
Serial.print(encoderLastChange);
43+
Serial.print("; Encoder value: ");
44+
Serial.print(encoderNewValue);
45+
Serial.print("; Encoder last value: ");
46+
Serial.println(encoderCurrentValue);
47+
encoderCurrentValue = encoderNewValue;
48+
encoderLastChange = currentTime;
2749
}
28-
encod = newEnc;
29-
Serial.println(newEnc);
30-
delay(20);
3150
}
3251
}

0 commit comments

Comments
 (0)