Revalogics
Well-known member
Hi, I'm currently working on creating a library to read an encoder.
Basically, it reads encoder pins and automatically debounces it.
Also, I made it to set flags if it was rotated, and set direction flags.
I'm not into counting encoder steps kind of thing.
One problem arises: I can't succesfully include attachInterrupt functions inside the library to create interrupts when those pins changed.
This awkward code works with my hardware:
These three, when together, works as expected.
My goal here is to abstract all "attachInterrupt" calls inside the sketch and have it included inside the library, like this:
with this test sketch:
Basically, it reads encoder pins and automatically debounces it.
Also, I made it to set flags if it was rotated, and set direction flags.
I'm not into counting encoder steps kind of thing.
One problem arises: I can't succesfully include attachInterrupt functions inside the library to create interrupts when those pins changed.
This awkward code works with my hardware:
Code:
// contents of the library "R_Encoder.h"
#ifndef R_Encoder_h
#define R_Encoder_h
#include "Arduino.h"
class R_Encoder {
public:
R_Encoder(uint8_t pin1, uint8_t pin2, uint32_t debounce) {
pinMode(pin1, INPUT_PULLUP);
pinMode(pin2, INPUT_PULLUP);
pins[0] = pin1;
pins[1] = pin2;
debounceTime = debounce;
}
bool wasRotated() {
bool temp = rotated;
rotated = 0;
return temp;
}
bool goesRight() {return direction;}
void interrupt() {
static byte pos;
bool pinState[2];
pinState[0] = digitalReadFast(pins[0]);
pinState[1] = digitalReadFast(pins[1]);
if(t >= debounceTime) {
t = 0;
if(pinState[0] && pinState[1]) pos = 0;
else if(pinState[0] && !pinState[1]) pos = 1;
else if(!pinState[0] && !pinState[1]) {
if(pos == 3) direction = 0;
else if(pos == 1) direction = 1;
pos = 2;
rotated = 1;
}
else if(!pinState[0] && pinState[1]) pos = 3;
}
}
uint8_t pins[2];
private:
elapsedMillis t;
volatile bool rotated, direction;
uint32_t debounceTime;
};
#endif
Code:
// contents of "R_Encoder.cpp"
#include "R_Encoder.h"
Code:
// contents of test sketch "R_Encoder_test.ino"
#define LD7 2
#define LD6 4
#define LD5 5
#define LD4 6
#define LEN 7
#define LRW 8
#define LRS 9
#define ENC1A 33
#define ENC1B 34
#define ENC2A 37
#define ENC2B 38
#include <LiquidCrystalFast.h>
LiquidCrystalFast MC2004(LRS, LRW, LEN, LD4, LD5, LD6, LD7);
#include <R_Encoder.h>
R_Encoder encoder1(ENC1A, ENC1B, 5);
R_Encoder encoder2(ENC2A, ENC2B, 5);
//#include <Encoder.h>
//Encoder encoder1(ENC1A, ENC1B);
//Encoder encoder2(ENC2A, ENC2B);
elapsedMillis t;
long count[2];
void setup() {
Serial.begin(115200);
MC2004.begin(20, 4);
MC2004.clear();
attachInterrupt(encoder1.pins[0], wut1, CHANGE);
attachInterrupt(encoder1.pins[1], wut1, CHANGE);
attachInterrupt(encoder2.pins[0], wut2, CHANGE);
attachInterrupt(encoder2.pins[1], wut2, CHANGE);
}
void loop() {
if(t >= 50) {
t = 0;
/**/
if(encoder1.wasRotated()) {
if(encoder1.goesRight()) count[0]++;
else count[0]--;
}
if(encoder2.wasRotated()) {
if(encoder2.goesRight()) count[1]++;
else count[1]--;
}
/*
if(encoder1.read() > 0) count[0]++;
else if(encoder1.read() < 0) count[0]--;
if(encoder2.read() > 0) count[1]++;
else if(encoder2.read() < 0) count[1]--;
encoder1.write(0);
encoder2.write(0);
/**/
MC2004.setCursor(0, 0);
MC2004.print(count[0]);
MC2004.print(" ");
MC2004.setCursor(0, 1);
MC2004.print(count[1]);
MC2004.print(" ");
MC2004.setCursor(0, 2);
MC2004.setCursor(0, 3);
}
}
void wut1() {encoder1.interrupt();}
void wut2() {encoder2.interrupt();}
My goal here is to abstract all "attachInterrupt" calls inside the sketch and have it included inside the library, like this:
Code:
#ifndef R_Encoder_h
#define R_Encoder_h
#include "Arduino.h"
class R_Encoder {
public:
R_Encoder(uint8_t pin1, uint8_t pin2, uint32_t debounce) {
pinMode(pin1, INPUT_PULLUP);
pinMode(pin2, INPUT_PULLUP);
pins[0] = pin1;
pins[1] = pin2;
debounceTime = debounce;
}
void begin() {
attachInterrupt(pins[0], interrupt, CHANGE);
attachInterrupt(pins[1], interrupt, CHANGE);
}
bool wasRotated() {
bool temp = rotated;
rotated = 0;
return temp;
}
bool goesRight() {return direction;}
private:
void interrupt() {
static byte pos;
bool pinState[2];
pinState[0] = digitalReadFast(pins[0]);
pinState[1] = digitalReadFast(pins[1]);
if(t >= debounceTime) {
t = 0;
if(pinState[0] && pinState[1]) pos = 0;
else if(pinState[0] && !pinState[1]) pos = 1;
else if(!pinState[0] && !pinState[1]) {
if(pos == 3) direction = 0;
else if(pos == 1) direction = 1;
pos = 2;
rotated = 1;
}
else if(!pinState[0] && pinState[1]) pos = 3;
}
}
elapsedMillis t;
volatile bool rotated, direction;
uint8_t pins[2];
uint32_t debounceTime;
};
#endif
Code:
#define LD7 2
#define LD6 4
#define LD5 5
#define LD4 6
#define LEN 7
#define LRW 8
#define LRS 9
#define ENC1A 33
#define ENC1B 34
#define ENC2A 37
#define ENC2B 38
#include <LiquidCrystalFast.h>
LiquidCrystalFast MC2004(LRS, LRW, LEN, LD4, LD5, LD6, LD7);
#include <R_Encoder.h>
R_Encoder encoder1(ENC1A, ENC1B, 5);
R_Encoder encoder2(ENC2A, ENC2B, 5);
//#include <Encoder.h>
//Encoder encoder1(ENC1A, ENC1B);
//Encoder encoder2(ENC2A, ENC2B);
elapsedMillis t;
long count[2];
void setup() {
Serial.begin(115200);
MC2004.begin(20, 4);
MC2004.clear();
encoder1.begin();
encoder2.begin();
}
void loop() {
if(t >= 50) {
t = 0;
/**/
if(encoder1.wasRotated()) {
if(encoder1.goesRight()) count[0]++;
else count[0]--;
}
if(encoder2.wasRotated()) {
if(encoder2.goesRight()) count[1]++;
else count[1]--;
}
/*
if(encoder1.read() > 0) count[0]++;
else if(encoder1.read() < 0) count[0]--;
if(encoder2.read() > 0) count[1]++;
else if(encoder2.read() < 0) count[1]--;
encoder1.write(0);
encoder2.write(0);
/**/
MC2004.setCursor(0, 0);
MC2004.print(count[0]);
MC2004.print(" ");
MC2004.setCursor(0, 1);
MC2004.print(count[1]);
MC2004.print(" ");
MC2004.setCursor(0, 2);
MC2004.setCursor(0, 3);
}
}