Hello.
I am working with the ClickEncoder library for rotary encoders.
I am using two encoders with buttons.
The rotation works fine in both of them.
The problem is that the second encoder's button does not work.
The software does not understand that it is pressed.
When I am enabling only one of the encoders, then it will work OK, it does not matter which one.
Anyone having the same issue?
A bit more advanced:
When using the JTAG mkII and debugging, I can see that in the function ClickEncoder::service, when entering the if statement
if(digitalRead(pinBTN) == pinsActive)
{...} it always returns fault.
However, if I change the statement to
if(digitalRead(38) == pinsActive)
{...}
then it works.
It seems that pinBTN always have the value of only one of the encoders.
Perhaps something in the C++ code gets confused. Or perhaps it is the stack or anything else.
Anyone can help?
Thanks a lot!!!
ClickEncoder library problem.
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: ClickEncoder library problem.
Post your full code (between CODE tags please) and a photo of your hardware. We'll see if those give us any clues.
-
- Posts: 15
- Joined: Mon Aug 13, 2012 6:15 am
Re: ClickEncoder library problem.
Thanks, here is the code. The base code is from the example and I changed it because I was playing around.adafruit_support_mike wrote:Post your full code (between CODE tags please) and a photo of your hardware. We'll see if those give us any clues.
In my previous post, it is digitalRead(40), not digitalRead(38).
Code: Select all
#include <ClickEncoder.h>
#include <TimerOne.h>
#include <LiquidCrystal.h>
#define RED_R 4
#define GREEN_R 5
#define RED_L 7
#define GREEN_L 6
#define LCD_RS 22
#define LCD_RW 23
#define LCD_EN 24
#define LCD_D4 29
#define LCD_D5 30
#define LCD_D6 31
#define LCD_D7 32
#define LCD_CHARS 20
#define LCD_LINES 4
LiquidCrystal lcd(LCD_RS, LCD_RW, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
ClickEncoder *encoder1, *encoder2;
int16_t last1, value1, last2, value2, rightButtonClicks = 0, rightButtonDoubleClicks = 0, leftButtonClicks = 0, leftButtonDoubleClicks = 0;
void timerIsr() {
encoder1->service();
encoder2->service();
}
void displayAccelerationStatus() {
lcd.setCursor(0, 1);
lcd.print("Double Clicks: ");
lcd.setCursor(6, 0);
lcd.print("Clicks: ");
lcd.setCursor(0, 3);
lcd.print("Double Clicks: ");
lcd.setCursor(6, 2);
lcd.print("Clicks: ");
}
void setup() {
Serial.begin(9600);
pinMode(GREEN_L, OUTPUT);
pinMode(GREEN_R, OUTPUT);
pinMode(RED_L, OUTPUT);
pinMode(RED_R, OUTPUT);
encoder1 = new ClickEncoder(35, 34, 36);
encoder2 = new ClickEncoder(39, 38, 40);
lcd.begin(LCD_CHARS, LCD_LINES);
lcd.clear();
displayAccelerationStatus();
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);
last1 = -1;
last2 = -1;
}
void loop() {
value1 += encoder1->getValue();
value2 += encoder2->getValue();
if (value1 != last1) {
last1 = value1;
Serial.print("Encoder Value1: ");
Serial.println(value1);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(value1);
}
if (value2 != last2) {
last2 = value2;
Serial.print("Encoder Value2: ");
Serial.println(value2);
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(value2);
}
ClickEncoder::Button b = encoder1->getButton();
if (b != ClickEncoder::Open)
{
switch (b)
{
case ClickEncoder::Held:
Serial.print("HEEEEEEEEDDDDDDDD\n");
digitalWrite(RED_R, HIGH);
break;
case ClickEncoder::Released:
Serial.print("right button Wow, at last released\n\n");
digitalWrite(RED_R, LOW);
break;
case ClickEncoder::Clicked:
rightButtonClicks ++;
Serial.print("right button Oh! You clicked me...\n");
lcd.setCursor(14, 0);
lcd.print(" ");
lcd.setCursor(14, 0);
lcd.print(rightButtonClicks);
break;
case ClickEncoder::DoubleClicked:
rightButtonDoubleClicks ++;
Serial.print("right button HOW DARE YOU DOUBLE CLICKING ME?!?!?!?!?!\n\n");
lcd.setCursor(15, 1);
lcd.print(" ");
lcd.setCursor(15, 1);
lcd.print(rightButtonDoubleClicks);
break;
}
}
ClickEncoder::Button c = encoder2->getButton();
if (c != ClickEncoder::Open)
{
switch (c)
{
case ClickEncoder::Held:
Serial.print("Left button HEEEEEEEEDDDDDDDD\n");
digitalWrite(RED_L, HIGH);
break;
case ClickEncoder::Released:
Serial.print("Left button Wow, at last released\n\n");
digitalWrite(RED_L, LOW);
break;
case ClickEncoder::Clicked:
leftButtonClicks ++;
Serial.print("Left button Oh! You clicked me...\n");
lcd.setCursor(14, 2);
lcd.print(" ");
lcd.setCursor(14, 2);
lcd.print(leftButtonClicks);
break;
case ClickEncoder::DoubleClicked:
leftButtonDoubleClicks ++;
Serial.print("left button HOW DARE YOU DOUBLE CLICKING ME?!?!?!?!?!\n\n");
lcd.setCursor(15, 3);
lcd.print(" ");
lcd.setCursor(15, 3);
lcd.print(leftButtonDoubleClicks);
break;
}
}
}
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: ClickEncoder library problem.
Hmm.. I did some digging through the ClickEncoder library here:
https://github.com/0xPIT/encoder/blob/m ... ncoder.cpp
and found something that looks suspicious. In the part of the service routine that reads the button, there's a set of static variables that handle debounce timing:
In C++, static variables generally belong to the class and not to the object. No matter how many objects you have, there's only one copy of each variable and they all have access to it.
There are ways to use that well (Singleton patterns), but this isn't one of them. This is called 'non-reentrant code', which translates roughly to "don't try to use more than one."
The most obvious solution would be to move those values out of the function and into the object.
https://github.com/0xPIT/encoder/blob/m ... ncoder.cpp
and found something that looks suspicious. In the part of the service routine that reads the button, there's a set of static variables that handle debounce timing:
Code: Select all
// handle button
//
#ifndef WITHOUT_BUTTON
static uint16_t keyDownTicks = 0;
static uint8_t doubleClickTicks = 0;
static unsigned long lastButtonCheck = 0;
There are ways to use that well (Singleton patterns), but this isn't one of them. This is called 'non-reentrant code', which translates roughly to "don't try to use more than one."
The most obvious solution would be to move those values out of the function and into the object.
-
- Posts: 15
- Joined: Mon Aug 13, 2012 6:15 am
Re: ClickEncoder library problem.
Thank you very much mike!
I think that it is time for me to start digging more into C++.
I will try that this afternoon and let you know.
Thanks again.
I think that it is time for me to start digging more into C++.
I will try that this afternoon and let you know.
Thanks again.
-
- Posts: 15
- Joined: Mon Aug 13, 2012 6:15 am
Re: ClickEncoder library problem.
Hi again.
Indeed, as you said the problem had something to do with these variables.
I made them class members and both buttons work now.
I am facing a couple of bugs but I don't think it is a big deal.
When I solve the bugs, I will come back here to ask how to post a bug fix in the library.
Thanks again Mike.
Indeed, as you said the problem had something to do with these variables.
I made them class members and both buttons work now.
I am facing a couple of bugs but I don't think it is a big deal.
When I solve the bugs, I will come back here to ask how to post a bug fix in the library.
Thanks again Mike.
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: ClickEncoder library problem.
I don't think that's one of our libraries, so you'll need to contact the creator. Github has features to support that on the repo page.
- sonicdh
- Posts: 7
- Joined: Sun Jan 23, 2011 4:24 pm
Re: ClickEncoder library problem.
Hey kostbill, I'm not a particularly savvy coder. Can you post how to enact your fix?
-
- Posts: 15
- Joined: Mon Aug 13, 2012 6:15 am
Re: ClickEncoder library problem.
Hello.SonicDH wrote:Hey kostbill, I'm not a particularly savvy coder. Can you post how to enact your fix?
I am attaching the files.
I declared some variables as Class members, instead of declaring them as local variables inside the Class function, as Mike mentioned.
I also added a small function named direction, so you can figure out which way the encoder turns.
If you have any questions or if you find any bug or problem, please let me know.
- Attachments
-
- ClickEncoder.h
- (2.82 KiB) Downloaded 454 times
-
- ClickEncoder.cpp
- (5.87 KiB) Downloaded 597 times
- sonicdh
- Posts: 7
- Joined: Sun Jan 23, 2011 4:24 pm
Re: ClickEncoder library problem.
Thanks! You should fork the library and document it.
-
- Posts: 15
- Joined: Mon Aug 13, 2012 6:15 am
Re: ClickEncoder library problem.
Hi!
Bit lazy for that. Maybe this weekend.
Bit lazy for that. Maybe this weekend.
Please be positive and constructive with your questions and comments.