Transitioning from "Rotary" library to "Encoder" libary?

Status
Not open for further replies.

Xnke

New member
I am working on a fairly large project based on an ATmega2561, and seem to have caused myself some issues when I did the hardware design and PCB layout.

This is the "Megacore" pin assignments, (the core I'm using to make my ATmega2561 Arduino-compatible:

687474703a2f2f692e696d6775722e636f6d2f657a354d7976492e6a7067


Instead of tying my encoder to the PCINTx pins, I tied my encoder to the INTx pins-which while OK, isn't exactly convenient when using Rotary.h:

Code:
#include <Rotary.h>

Rotary r = Rotary(20, 21);

const byte encoderbutton = 22;
const byte button2 = 23;
const byte button3 = 24;
const byte button4 = 25;

int Encoderbutton = 0;
int Button2 = 0;
int Button3 = 0;
int Button4 = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("started the console");
  EICRA |= (1 << EICRA);
  EIMSK |= (1 << INT2) | (1 << INT3);
  sei();

  pinMode(encoderbutton, INPUT);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);
}

void loop() {

Encoderbutton = digitalRead(encoderbutton);
Button2 = digitalRead(button2);
Button3 = digitalRead(button3);
Button4 = digitalRead(button4);

if (Encoderbutton == LOW) {
    // turn LED on:
    Serial.println("encoderbutton pushed!");
  } else {
    // turn LED off:
    //Serial.println("");
  }

if (Button2 == LOW) {
    // turn LED on:
    Serial.println("Button 2 pushed");
  } else {
    // turn LED off:
   
  }

  if (Button3 == LOW) {
    // turn LED on:
    Serial.println("Button 3 pushed");
  } else {
    // turn LED off:
    //Serial.println("");
  }

  if (Button4 == LOW) {
    // turn LED on:
    Serial.println("Button 4 pushed");
  } else {
    // turn LED off:
   // Serial.println("");
  }
}

ISR(INT2_vect) {
  unsigned char result = r.process();
  if (result == DIR_NONE) {
    // do nothing
  }
  else if (result == DIR_CW) {
    Serial.println("ClockWise");
  }
  else if (result == DIR_CCW) {
    Serial.println("CounterClockWise");
  }
}
 ISR(INT3_vect) {
  unsigned char result = r.process();
  if (result == DIR_NONE) {
    // do nothing
  }
  else if (result == DIR_CW) {
    Serial.println("ClockWise");
  }
  else if (result == DIR_CCW) {
    Serial.println("CounterClockWise");
  }
}

The above code works as expected...Serial.println() inside the ISR is goofy and broken but it does what I ask it to do here. The issue is that this is the only case of using Buxton's Rotary.h libary that I have seen the need for twin ISR's...remove one and the micro resets every time the interrupt pin is toggled by the encoder.

The plan is to use the encoder to increment/deincrement menus, delineated by the pushbutton, so i'm only incrementing and deincrementing a variable-the pushbutton will have to select the variable that I am incrementing and deincrementing, though.

I have LOTS of examples of how to control the clock generator with the Rotary library, but all with the single ISR...so I am looking at transitioning to the "Encoder" library to maybe make things easier to work with.

Does anyone have any advice on how and why I might want to use one over the other, outside of the "twin ISR" concern?
 
Most probably the wrong forum here... This one is mainly about the Teensy micro-controllers, manufactured by PJRC. On these, each digital pin, and they have much of these, is interrupt capable, so that you can basically have up to 10 or 12 encoders connected, each using 2 individual pin interrupt routines for optimal performance.

I've written an optimized encoder class, making use of these extended capabilities and even doing contact debouncing by enabling and disabling interrupts "on the fly" by directly accessing the pin interrupt control registers of the Teensy. But I fear that it can't be used on the ATMegas with their different hardware architecture.
 
Seeing as the library was written by PJRC, I figured this would be *the* place to ask.

Anyway-I need to add support for my board, so I figure once I've done that the library will work for me just as well. I have added the following to the "interrupt_pins.h" file.

Code:
//"Megacore" based board
#elif defined(__AVR_ATmega128__) || defined(__AVR_ARmega1281__) || defined(__AVR_ARmega2561__)
  #define CORE_NUM_INTERRUPT    17
  #define CORE INT0_PIN               18
  #define CORE_INT1_PIN		19
  #define CORE_INT2_PIN		20
  #define CORE_INT3_PIN		21
  #define CORE_INT4_PIN		4
  #define CORE_INT5_PIN		5
  #define CORE_INT6_PIN		6
  #define CORE_INT7_PIN		7
  #define CORE_INT8_PIN		8
  #define CORE_INT9_PIN		9
  #define CORE_INT10_PIN	10
  #define CORE_INT11_PIN	11
  #define CORE_INT12_PIN	12
  #define CORE_INT13_PIN	13
  #define CORE_INT14_PIN	14
  #define CORE_INT15_PIN	15
  #define CORE_INT16_PIN	16
  #define CORE_INT17_PIN     0

Now, Interrupts 0-7 are listed as INT, and interrupts 8-17 are PCINT-do I need to change the definition descriptors in this file?

EDIT:

Adding the above to the file did not solve the issue, I got this in return:

Code:
C:\Users\Jake\Documents\Arduino\libraries\Encoder/utility/interrupt_pins.h:224:2: error: #error "Interrupts are unknown for this board, please add to this code"

 #error "Interrupts are unknown for this board, please add to this code"

  ^

C:\Users\Jake\Documents\Arduino\libraries\Encoder/utility/interrupt_pins.h:227:2: error: #error "Encoder requires interrupt pins, but this board does not have any :("

 #error "Encoder requires interrupt pins, but this board does not have any :("

  ^

C:\Users\Jake\Documents\Arduino\libraries\Encoder/utility/interrupt_pins.h:228:2: error: #error "You could try defining ENCODER_DO_NOT_USE_INTERRUPTS as a kludge."

 #error "You could try defining ENCODER_DO_NOT_USE_INTERRUPTS as a kludge."

  ^

exit status 1
Error compiling for board ATmega2561.

EDIT: Problem solved. Typos are the worst bugs.
 
Last edited:
Only significant issue right now-I need to divide the count by four, but since I'm working with so many variables that get incremented/deincremented, I need to actually divide the count-not the variable.
 
So this is where I got to-short of debouncing, it counts the encoder the way I need.


Code:
#include <Encoder.h>

Encoder myEnc(20, 21);

const byte encoderbutton = 22;
const byte button2 = 23;
const byte button3 = 24;
const byte button4 = 25;

int Encoderbutton = 0;
int Button2 = 0;
int Button3 = 0;
int Button4 = 0;

long oldPosition = -999;

void setup() {
  Serial.begin(9600);
  Serial.println("started the console");
  
  pinMode(encoderbutton, INPUT);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);
}


void loop() {

Encoderbutton = digitalRead(encoderbutton);
Button2 = digitalRead(button2);
Button3 = digitalRead(button3);
Button4 = digitalRead(button4);

long newPosition = myEnc.read()>>2;
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }

if (Encoderbutton == LOW) {
    // turn LED on:
    Serial.println("encoderbutton pushed!");
  } else {
    // turn LED off:
    //Serial.println("");
  }

if (Button2 == LOW) {
    // turn LED on:
    Serial.println("Button 2 pushed");
  } else {
    // turn LED off:
   
  }

  if (Button3 == LOW) {
    // turn LED on:
    Serial.println("Button 3 pushed");
  } else {
    // turn LED off:
    //Serial.println("");
  }

  if (Button4 == LOW) {
    // turn LED on:
    Serial.println("Button 4 pushed");
  } else {
    // turn LED off:
   // Serial.println("");
  }
}
 
Status
Not open for further replies.
Back
Top