Skip to content

Instantly share code, notes, and snippets.

@calaveraInfo
Last active December 27, 2015 14:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save calaveraInfo/cd60cb4bab480a7fefe7 to your computer and use it in GitHub Desktop.
Save calaveraInfo/cd60cb4bab480a7fefe7 to your computer and use it in GitHub Desktop.
Use rotary encoder with Arduino Micro to increase/decrease a value and show that value on SSD1306 display. Based on https://learn.adafruit.com/pro-trinket-rotary-encoder/example-rotary-encoder-volume-control
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_DC 6
#define OLED_CS 7
#define OLED_RESET 8
#define PIN_ENCODER_A 4 //Micro pin 4 - encoder A
#define PIN_ENCODER_B 6
#define PIN_ENCODER_BX 12 //Micro pin 12 - encoder B
#define ARDUINO_PINx PIND
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
static uint8_t enc_prev_pos = 0;
static uint8_t enc_flags = 0;
int displayedNumber = 0;
const int ledPin = 13;
void setup()
{
// set pins as input with internal pull-up resistors enabled
pinMode(PIN_ENCODER_A, INPUT);
pinMode(PIN_ENCODER_BX, INPUT);
digitalWrite(PIN_ENCODER_A, HIGH);
digitalWrite(PIN_ENCODER_BX, HIGH);
display.begin(SSD1306_SWITCHCAPVCC);
display.display(); // show splashscreen
//delay(2000);
//display.clearDisplay();
// get an initial reading on the encoder pins
if (digitalRead(PIN_ENCODER_A) == LOW)
{
enc_prev_pos |= (1 << 0);
}
if (digitalRead(PIN_ENCODER_BX) == LOW)
{
enc_prev_pos |= (1 << 1);
}
}
void loop()
{
int8_t enc_action = 0; // 1 or -1 if moved, sign is direction
// note: for better performance, the code will now use
// direct port access techniques
// http://www.arduino.cc/en/Reference/PortManipulation
uint8_t enc_cur_pos = 0;
// read in the encoder state first
if (bit_is_clear(ARDUINO_PINx, PIN_ENCODER_A))
{
enc_cur_pos |= (1 << 0);
}
if (bit_is_clear(ARDUINO_PINx, PIN_ENCODER_B))
{
enc_cur_pos |= (1 << 1);
}
// if any rotation at all
if (enc_cur_pos != enc_prev_pos)
{
if (enc_prev_pos == 0x00)
{
// this is the first edge
if (enc_cur_pos == 0x01)
{
enc_flags |= (1 << 0);
}
else if (enc_cur_pos == 0x02)
{
enc_flags |= (1 << 1);
}
}
if (enc_cur_pos == 0x03)
{
// this is when the encoder is in the middle of a "step"
enc_flags |= (1 << 4);
}
else if (enc_cur_pos == 0x00)
{
// this is the final edge
if (enc_prev_pos == 0x02)
{
enc_flags |= (1 << 2);
}
else if (enc_prev_pos == 0x01)
{
enc_flags |= (1 << 3);
}
// check the first and last edge
// or maybe one edge is missing, if missing then require the middle state
// this will reject bounces and false movements
if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4)))
{
enc_action = 1;
}
else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4)))
{
enc_action = 1;
}
else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4)))
{
enc_action = -1;
}
else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4)))
{
enc_action = -1;
}
enc_flags = 0; // reset for next time
}
}
enc_prev_pos = enc_cur_pos;
if (enc_action > 0)
{
draw(++displayedNumber);
digitalWrite(ledPin, HIGH);
}
else if (enc_action < 0)
{
digitalWrite(ledPin, LOW);
draw(--displayedNumber);
}
else {
// do nothing
}
}
void draw(int number) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(number);
display.display();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment