An archive of community.esquilo.io as of Saturday January 26, 2019.

Rotary Encoder and GPIO onchange(), onrising(), onfalling()

JefferyS

Hi I'm trying to get a Rotary Encoder to work. I actually have a Grove Encoder module. It already has pullup resistors on the board with the encoder. http://wiki.seeed.cc/Grove-Encoder/

I can read the pins and they are changing but I can't seem to get any of the onchange() or others to work.

require(["GPIO", "I2C", "system", "string"]);

encoder1 <- GPIO(22);
encoder2 <- GPIO(23);

encoder1.input();
encoder2.input();


encoder1.onrising(
    function(c){
        printLn("C: " + c);
    }
);
encoder2.onfalling(
    function(c){
        printLn("C: " + c);
    }
);

I've changed them to onchange() but currently tried the onrising() and onfalling().

I'm not sure if my syntax is not correct though I don't have any errors or I'm missing some other setting.

I did put a loop at the end to see the changes.

while(true) {
    delay(1000);
    printLn("encoder1: " + encoder1.read());
    printLn("encoder2: " + encoder2.read());
}

So the two pins are changing to high and low depending on how I turn the knob.

Thanks,

Jeffery

JefferyS

Update:

It is doing what it is supposed to, it's hitting the function but evidently it is so fast that the print or anything else I try there doesn't register. How do I know this, I removed "c" from the function and the printLn got a runtime error but it didn't kill the nut, it still kept going running the while loop.
I even put a delay to see if that would help, instead of print I used error() to see if that would show on the console and have more priority or something, I tried setting a variable in the onrising and onfalling functions for the print in the while loop, changed the code many times now.

softwarejanitor

I have a couple of rotary encoders. If I get a chance I will dig one out and try your code with it.

JefferyS

That would be great, thanks!

JefferyS

Here is some more code I've been playing with.

require(["GPIO", "I2C", "system", "string"]);

dofile("sd:/common/utilities.nut");


encoder1 <- GPIO(22);
encoder2 <- GPIO(23);

encoder1.input();
encoder2.input();

msg <- 0;

encoder1.onchange(
    function(c){
        msg = 1;
    }
);

encoder2.onchange(
    function(d){
        msg = 2;
    }
);


while(true) {
    delay(1500);
    printLn("message: " + msg);
    //printLn("encoder2: " + encoder2.read());
}

Utilities.nut

// Returns the Date and time
function DateTimeFormat() {
    local t = date();
    return format("%02d-%02d-%04d %02d:%02d:%02d", (t.month + 1), t.day, t.year, t.hour, t.min, t.sec);
}

// Returns the Date
function DateFormat() {
    local t = date();
    return format("%02d_%02d_%04d", (t.month + 1), t.day, t.year);
}

// Returns Date Time format for log
function LogDateTimeFormat() {
    local t = date();
    return format("[%04d-%02d-%02d %02d:%02d:%02d] ", t.year, (t.month + 1), t.day, t.hour, t.min, t.sec);
}

// Returns the Date format for the log file
function FileDateFormat() {
    local t = date();
    return format("%04d_%02d_%02d", t.year, (t.month + 1), t.day);
}


// Prints a line with Carriage Return
function printLn(str) {
    print(str + "\r\n");   
}
gwittie

Here is my most reliable rotary encode nut file that I have so far. I am using the encoder from Adafruit. I have been trying to get a class file generated with the encoder code but I am having major problems with the class variables not being recognized in the encoder class tick function. I also have not tried to merge this code with any other code. I would be concerned with the priority command that could interfere with I2C, USB, or network traffic. I expect these to slow down due to the priority being so high for the encoder and the encode may miss some changes.


// Interrupt Rotator Demo
//
// This example checks the state of the rotary encoder in the while loop.
// The current position is printed on output when changed.
//
// Hardware setup:
// Checked out with BOURNS PEC11-4215F-S24 rotary encoder from Adafruit.com
// Attach a rotary encoder with output pins to rencA=GPIO(8) and rencB=GPIO(9)
// The common contact should be attached to ground.
// Attached encoder switch to GPIO(7) with pullup and other switch contact to ground.
//

// Local function to generate directional increment with knob movement
function tick() {
local sig1 = encA.read();
local sig2 = encB.read();

thisState = sig1 | (sig2 << 1);

if (oldState != thisState) {
position += KNOBDIR[thisState | (oldState<

if (thisState == LATCHSTATE) positionExt = position >> 2;

oldState = thisState;

}
}
require("GPIO");
LATCHSTATE <- 3;
thisState <- 0;
oldState <- 0;
position <- 0;
positionExt <- 0;
KNOBDIR <- [0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0];
encA <- null;
encB <- null;
Apin <- 8;
Bpin <- 9;
newPos <- 0;
pos <- 0;

// Setup the input pins
encA = GPIO(Apin);
encA.input();
encA.pullup(true);
encA.onchange(tick);
priority(PRIO_HIGHEST);

encB = GPIO(Bpin);
encB.input();
encB.pullup(true);
encB.onchange(tick);

// Switch is on pin 7 (need to add check for closure)
local button = GPIO(7);
button.input();
button.pullup(true);

print("SimplePollRotator example for the RotaryEncoder library:\n");
while (button.ishigh()) {
delay(50);
newPos = positionExt;
if (pos != newPos) {
print(newPos+"\n");
pos = newPos;
}
}

// Stop onchange interrupts on A and B encoder inputs and lower priority
encA.onchange(null);
encB.onchange(null);
priority(PRIO_NORMAL);

// The End


JefferyS

Hi, some of the code in the tick function isn't showing correctly.

Thanks,

Jeffery

gwittie

Jeffery,
This missing contents of the if statement in the tick function:

if (oldState != thisState) {
position += KNOBDIR[thisState | (oldState << 2)];

if (thisState == LATCHSTATE) positionExt = position >> 2;

oldState = thisState;

}

Regards,
Gary

JefferyS

Thanks Gary, your code works great.

How can I make it count the opposite where clockwise is positive and counter clockwise is negative?

Thanks,

Jeffery

gwittie

Jeffery,
Just change the += to -=.

position -= KNOBDIR[thisState | (oldState << 2)]

Gary