Skip to content

Instantly share code, notes, and snippets.

@zeroeth
Created July 25, 2011 06:22
Show Gist options
  • Save zeroeth/1103653 to your computer and use it in GitHub Desktop.
Save zeroeth/1103653 to your computer and use it in GitHub Desktop.

Revisions

  1. zeroeth created this gist Jul 25, 2011.
    212 changes: 212 additions & 0 deletions arduino_rotary_encoder.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,212 @@
    // 2 INT Rotary Knob decoder.
    // by Kevin Alford (zeroeth) JUL-25-2011
    // http://pixelflow.org http://github.com/zeroeth
    //
    // Description:
    // This code does pattern matching on pin change to find valid rotations and filter out bad data.
    // Events: 1/3 A HI/LO, 2/3 A HI/LO
    // Valid transitions: Clock-wise 3412, Counterclock-wise 4321

    #include <SoftwareSerial.h>

    #define txPin 4
    SoftwareSerial LCD = SoftwareSerial(-1, txPin);

    #define encoderPinA 2
    #define encoderPinB 3

    #define buffer_length 4
    int pattern_buffer[buffer_length] = {0};
    int expected_value = 0;
    int wheel_value = 0;
    char wheel_value_str[5] = {0};


    // SETUP //////////////////////////////////////

    void setup() {
    lcd_setup();
    encoder_setup();
    }

    void encoder_setup() {
    pinMode(encoderPinA, INPUT);
    pinMode(encoderPinB, INPUT);

    digitalWrite(encoderPinA, HIGH);
    digitalWrite(encoderPinB, HIGH);

    attachInterrupt(0, intA, CHANGE);
    attachInterrupt(1, intB, CHANGE);
    }

    void lcd_setup() {
    pinMode(txPin, OUTPUT);
    LCD.begin(9600);
    delay (1000);
    backlightOn();
    clearLCD();
    }


    // MAIN LOOP ////////////////////////////////////

    void loop()
    {
    delay(1000);
    }


    // INTERRUPTS ///////////////////////////////////

    // Look at pin change, and opposite pin to set next valid value, ignore if invalid.

    void intA() {
    int pin_a = digitalRead(encoderPinA);
    int pin_b = digitalRead(encoderPinB);

    if (pin_a == HIGH) {
    if (expected_value == 0 || expected_value == 1) {
    push_state(1);
    match_and_display();

    if (pin_b == LOW) {
    expected_value = 2;
    }
    else {
    expected_value = 4;
    }
    }
    }
    else {
    if (expected_value == 0 || expected_value == 3) {
    push_state(3);
    match_and_display();

    if (pin_b == LOW) {
    expected_value = 2;
    }
    else {
    expected_value = 4;
    }
    }
    }
    }


    void intB() {
    int pin_b = digitalRead(encoderPinB);
    int pin_a = digitalRead(encoderPinA);

    if (pin_b == HIGH) {
    if (expected_value == 0 || expected_value == 2) {
    push_state(2);
    match_and_display();

    if (pin_a == LOW) {
    expected_value = 1;
    }
    else {
    expected_value = 3;
    }
    }
    }
    else {
    if (expected_value == 0 || expected_value == 4) {
    push_state(4);
    match_and_display();

    if (pin_a == LOW) {
    expected_value = 1;
    }
    else {
    expected_value = 3;
    }
    }
    }
    }


    // PATTERN MATCHING /////////////////////////////

    // push to end of array, pop out oldest value

    void push_state(int value) {
    for(int i = 0; i < buffer_length-1; i++) {
    pattern_buffer[i] = pattern_buffer[i+1];
    }
    pattern_buffer[buffer_length-1] = value;
    }


    // Show us the pattern, match it, and increment/decrement the value

    void match_and_display() {
    selectLineOne();
    LCD.print(pattern_buffer[0]);
    LCD.print(pattern_buffer[1]);
    LCD.print(pattern_buffer[2]);
    LCD.print(pattern_buffer[3]);

    if (pattern_buffer[0] == 3 &&
    pattern_buffer[1] == 4 &&
    pattern_buffer[2] == 1 &&
    pattern_buffer[3] == 2) {
    wheel_value += 1;
    }
    else if (pattern_buffer[0] == 4 &&
    pattern_buffer[1] == 3 &&
    pattern_buffer[2] == 2 &&
    pattern_buffer[3] == 1) {
    wheel_value -= 1;
    }

    selectLineTwo();
    sprintf(wheel_value_str, "%-4d", wheel_value);
    LCD.print(wheel_value_str);

    }


    // Sparkfun serial LCD code /////////////////////

    void selectLineOne(){ //puts the cursor at line 0 char 0.
    goTo(0);
    }
    void selectLineTwo(){ //puts the cursor at line 0 char 0.
    goTo(16);
    }

    void goTo(int position) {
    //position = line 1: 0-15, line 2: 16-31, 31+ defaults back to 0
    if (position<16){
    serCommand(); //command flag
    LCD.print((position+128), BYTE); //position
    }
    else if (position<32){
    serCommand(); //command flag
    LCD.print((position+48+128), BYTE); //position
    }
    else {
    goTo(0);
    }
    //delay(10);
    }

    void clearLCD(){
    serCommand(); //command flag
    LCD.print(0x01, BYTE); //clear command.
    delay(10);
    }
    void backlightOn(){ //turns on the backlight
    LCD.print(0x7C, BYTE); //command flag for backlight stuff
    LCD.print(157, BYTE); //light level.
    }
    void backlightOff(){ //turns off the backlight
    LCD.print(0x7C, BYTE); //command flag for backlight stuff
    LCD.print(128, BYTE); //light level for off.
    }
    void serCommand(){ //a general function to call the command flag for issuing all other commands
    LCD.print(0xFE, BYTE);
    //delay(10);
    }