ClickEncoder library problem.

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
kostbill
 
Posts: 15
Joined: Mon Aug 13, 2012 6:15 am

ClickEncoder library problem.

Post by kostbill »

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!!!

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: ClickEncoder library problem.

Post by adafruit_support_mike »

Post your full code (between CODE tags please) and a photo of your hardware. We'll see if those give us any clues.

kostbill
 
Posts: 15
Joined: Mon Aug 13, 2012 6:15 am

Re: ClickEncoder library problem.

Post by kostbill »

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.
Thanks, here is the code. The base code is from the example and I changed it because I was playing around.
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;
    }
  }   
}


User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: ClickEncoder library problem.

Post by adafruit_support_mike »

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:

Code: Select all

  // handle button
  //
#ifndef WITHOUT_BUTTON
  static uint16_t keyDownTicks = 0;
  static uint8_t doubleClickTicks = 0;
  static unsigned long lastButtonCheck = 0;
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.

kostbill
 
Posts: 15
Joined: Mon Aug 13, 2012 6:15 am

Re: ClickEncoder library problem.

Post by kostbill »

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.

kostbill
 
Posts: 15
Joined: Mon Aug 13, 2012 6:15 am

Re: ClickEncoder library problem.

Post by kostbill »

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.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: ClickEncoder library problem.

Post by adafruit_support_mike »

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.

User avatar
sonicdh
 
Posts: 7
Joined: Sun Jan 23, 2011 4:24 pm

Re: ClickEncoder library problem.

Post by sonicdh »

Hey kostbill, I'm not a particularly savvy coder. Can you post how to enact your fix?

kostbill
 
Posts: 15
Joined: Mon Aug 13, 2012 6:15 am

Re: ClickEncoder library problem.

Post by kostbill »

SonicDH wrote:Hey kostbill, I'm not a particularly savvy coder. Can you post how to enact your fix?
Hello.

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

User avatar
sonicdh
 
Posts: 7
Joined: Sun Jan 23, 2011 4:24 pm

Re: ClickEncoder library problem.

Post by sonicdh »

Thanks! You should fork the library and document it.

kostbill
 
Posts: 15
Joined: Mon Aug 13, 2012 6:15 am

Re: ClickEncoder library problem.

Post by kostbill »

Hi!

Bit lazy for that. Maybe this weekend.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”