This is a follow-up to my previous writings on the subject of rotary encoders: Rotary Encoders on the i2c Bus. This time I am using the Sparkfun Rotary Encoder – Illuminated (RGB) (Part: COM-10982), this has the same rotary goodness as the SparkFun 12-step rotary encoder but with the addition of three LED’s to provide a whole host of colours on the rotating shaft.

Test Setup
Again I will be using the MCP23017 port expander to add 16 digital I/O ports to the Arduino via the i2c bus, the rotary encoder part operates in the same manner as before and we can use the internal pull-up resistors to reduce the number of components. The LED’s operate with a common anode and the push button also operates on 5v rather than the usual switching to ground.

For my test setup I have connected the rotary encoder to GPA0 and GPA1, the push button to GPA2 and the Red, Green and Blue LED’s to GPA5, GPA4 and GPA3. Note the 10K pull-down resistor on the push button.
My program on the Arduino changes the colours as you rotate the shaft, you will see seven colours, to see more you would need to use PWM to control the LED’s brightness. With the common anode on the LED’s the logic for switching them is inverted, so HIGH = off, LOW = on. You will need the Adafruit MCP23017 Arduino Library.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
#include <Wire.h> #include "Adafruit_MCP23017.h" // https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library // setup the port expander Adafruit_MCP23017 mcp0; #define ROT_A 0 #define ROT_B 1 #define ROT_BTN 2 #define ROT_RED 3 #define ROT_GRN 4 #define ROT_BLU 5 // some colours to display // because of the common anode on the LED's, logic is inverted: 0 = on, 1 = off // R G B boolean colours[8][3] = { {1, 1, 1}, // off (black) {1, 1, 0}, // blue {1, 0, 1}, // green {1, 0, 0}, {0, 1, 1}, // red {0, 1, 0}, {0, 0, 1}, {0, 0, 0}}; // white int colPointer = 0; unsigned long currentTime; unsigned long loopTime; int rotAprev=0; const int leds[3] = { ROT_RED, ROT_GRN, ROT_BLU }; void setColours(boolean colour[]) { for (int i=0; i<3; i++) { mcp0.digitalWrite(leds[i], colour[i]); } return; } void setup() { Serial.begin(9600); mcp0.begin(0); // 0 = i2c address 0x20 mcp0.pinMode(ROT_A, INPUT); // Rotary switch A mcp0.pullUp(ROT_A, HIGH); // turn on a 100K pullup internally mcp0.pinMode(ROT_B, INPUT); // Rotary switch B mcp0.pullUp(ROT_B, HIGH); // turn on a 100K pullup internally mcp0.pinMode(ROT_BTN, INPUT); // Push Button mcp0.pinMode(ROT_RED, OUTPUT); // Red mcp0.pinMode(ROT_GRN, OUTPUT); // Green mcp0.pinMode(ROT_BLU, OUTPUT); // Blue mcp0.digitalWrite(ROT_RED, HIGH); // all colours off mcp0.digitalWrite(ROT_GRN, HIGH); // HIGH = off, LOW = on mcp0.digitalWrite(ROT_BLU, HIGH); currentTime = millis(); loopTime = currentTime; Serial.println("ready"); setColours(colours[0]); } void loop() { currentTime = millis(); // check every 5 millisecs if(currentTime >= (loopTime + 5)) { int rotA = mcp0.digitalRead(ROT_A); int rotB = mcp0.digitalRead(ROT_B); // turn white if the button is pressed if (mcp0.digitalRead(ROT_BTN) == true) { setColours(colours[7]); } // see if there has been any rotation if((!rotA) && (rotAprev)) { if (rotB) { Serial.println("clockwise"); colPointer++; } else { Serial.println("counter-clockwise"); colPointer--; } // make sure the pointer stays within range if (colPointer > 7) { colPointer = 0; } if (colPointer < 0) { colPointer = 7; } Serial.print("pointer: "); Serial.println(colPointer); // set the shaft colour to that in pointer setColours(colours[colPointer]); } rotAprev = rotA; loopTime = currentTime; // Updates loopTime } } |
Links
- UK supplier: http://www.hobbytronics.co.uk/rotary-encoder-rgb they also have a useful breakout board for the switch
- MCP23017/MCP23S17 Data Sheet
- Rotary Encoder – Illuminated (RGB) Data Sheet
Can I “interrogate” you a bit about resistors?
I calculated the LED resistors to be 120 ohm for the red and 104 ohm for the green and blue but as this is only the second time I’ve tried resistor/LED calculations… I don’t exactly trust myself. and seeing your values of 220 ohms for all 3 has made me want to ask you how you came by those values.
I noticed you’ve got pull-up resistors on SCL and SDA… I’m using SPI not I2C, so it’s a bit different but I’ve not included pull-ups or pull-downs on any of my SPI lines… I’d love to hear opinions on that too.
Nice to see stuff online about projects with this encoder… there’s still not that much information around.
Hello Andrew.
Not sure about the SPI bus, I’ve not had chance to play with that sort of thing. The advice for pullups on the I2C bus seems to vary, I can’t remember why I put them in at the moment.
The 220R resistors on the LED’s are used to limit the current, LED’s will take all they can eat until they go pop. The datasheet for the rotary encoder says the forward current for the LEDs is 25mA.
So V / R = I: 5v / 220R = 0.023A x 1000 = 23mA. Or to put it another way: V / I = R: 5v / 0.025A = 200R, I used 220R as those are the best value I have below the maximum rating.
Addendum… I meant 68 ohms for the red and green LEDs
Thanks for that… and thanks again for the original post… some useful information on a “not discussed enough” component.
I did (5V – 2V) / 25mA = 120 Ohm
& (5V – 3.3V) / 25mA = 68 Ohm
But, like I said, I don’t trust that I’m doing the right thing.
where do these 2v and 3.3v come from? The voltage you use to calculate is whatever is on the common input (common anode) of the LED’s. The current also needs to be within the tolerance for that of the MCP23017.
2 & 3.3 – forward voltage of the LEDs
Yes, my bad, giving the wrong formula for LED’s earlier. But each GPIO pin on the the MCP23017 is limited to 25mA, and the maximum current overall is limited to 150mA, so the 220R resistor applies there. Another example:
http://www.learningaboutelectronics.com/Articles/MCP23017-IO-port-expander-circuit-with-arduino.php
Oh… I think I’m beginning to get it… you’re not only protecting the LEDs… you’re limiting the current load from the MCP23x17 too. Good job I saw this before going ahead and trusting my own calculations. Thanks again for this article.