// 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 #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); }