Teensy 3.2 joystick with rotary encoders

carcaes1

Well-known member
Hello everybody

I am using a rotary encoder ( http://www.ebay.es/itm/172178149195 )

And i have some questions for my sketch (I use Joystick button usb - USB TYPE Serial/Keyb/Mouse/Joystick).

I would like that each clockwise turn, activate the button 5, and each counterclockwise, button 6.

But not always works.

Which would be better way?

Thanks in advance.

Code:
#include <Encoder.h>


void setup() {
  Serial.begin(9600);
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();

  if (newPosition != oldPosition) {

          if( newPosition % 4 == 0) {     //for each 4 positions of encoder)

                if (newPosition > oldPosition){
                     Serial.print(newPosition);
                     Serial.println(" - Left");
                     Joystick.Button(5,1);
                     Joystick.Button(6,0);
                 } 

                 else {
                      Serial.print(newPosition);
                      Serial.println(" - Right");
                     Joystick.Button(5,0);
                     Joystick.Button(6,1);
                 }
           }
           oldPosition = newPosition;
           
  } else {   //encoder same position
           Joystick.Button(5,0);
           Joystick.Button(6,0);
   }

Joystick.send_now();
delay(4);


}
 
Last edited:
Check your actual encoder position values but first guess is that sometimes the encoder is skipping very quickly across two values and your code will miss checks if the encoder crosses through a %4 position in the 4ms wait time.
 
Check your actual encoder position values but first guess is that sometimes the encoder is skipping very quickly across two values and your code will miss checks if the encoder crosses through a %4 position in the 4ms wait time.

Thanks

I have tried without delay(4 ms) and still fails sometimes.


Code:
#include <Encoder.h>


void setup() {
  Serial.begin(9600);
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();

  if (newPosition != oldPosition) {

          if( newPosition % 4 == 0) {     //for each 4 positions of encoder)

                if (newPosition > oldPosition){
                     Serial.print(newPosition);
                     Serial.println(" - Left");
                     Joystick.Button(5,1);
                     Joystick.Button(6,0);
                 } 

                 else {
                      Serial.print(newPosition);
                      Serial.println(" - Right");
                     Joystick.Button(5,0);
                     Joystick.Button(6,1);
                 }
           }
           oldPosition = newPosition;
           
  } else {   //encoder same position
           Joystick.Button(5,0);
           Joystick.Button(6,0);
   }

Joystick.send_now();



}
 
Stripping the delay may still allow double counts if your encoder has detents that do not match the actual contacts internally. Problem remains that your code will not trigger unless you exactly hit a multiple of four.
Try
if (newPosition-oldPosition>1) Serial.println("double Count";)
after the newpos!=oldpos line, will only trigger in + direction of rotation but will tell you if things are amiss.

If this is what is happening then the fix needs to be some slightly more complex math detecting when you are more than 4 from the value you last toggled the button at, or having interupt driven code that tries to catch high speed transitions reliably.

If you aren't getting double counts then things are more mysterious but not seeing anything wrong with your code.
 
What are your actual symptoms of "not always works"?

What kind of code did you post? It can't be your real test code, "myEnc" is not declared and Joystick.Button() is a non-existing function, only Joystick.button() exists.

Your code doesn't account for contact bouncing, multiple button presses may be triggered or the direction may be wrong.

E.g. a test sketch:
Code:
#include <Encoder.h>

Encoder enc(6, 7);
uint32_t enc_prev_change_time = 0;

void setup() {
  Serial.begin(9600);
}

int32_t old_pos  = 0;

void loop() {
  int32_t new_pos = enc.read();
  if (new_pos != old_pos) {
    uint32_t enc_change_time = millis();
    if(abs(new_pos - old_pos) > 1) Serial.print("ERROR: large encoder change. ");
    Serial.print(millis());
    Serial.print(": ");
    Serial.print(new_pos);
    if(enc_change_time - enc_prev_change_time <= 3) Serial.println("   Encoder bouncing!");
    else Serial.println("");
    enc_prev_change_time = enc_change_time;
    old_pos = new_pos;
  }
}

Slowly rotating the encoder, output (output is [time in milliseconds, encoder value, possible bounce warning]):
[...]
12639: 15
12659: 16
13002: 17
13003: 16 Encoder bouncing!
13003: 17 Encoder bouncing!
13003: 16 Encoder bouncing!
13004: 17 Encoder bouncing!
13004: 16 Encoder bouncing!
13004: 17 Encoder bouncing!
13004: 16 Encoder bouncing!
13004: 17 Encoder bouncing!
13020: 18
13709: 19
 
Hi tni

Yes, you are right. In my code i have these changes

Encoder myEnc(5, 6);

And Joystick.button()

Sorry, but i had to write it in that post.

The fail is that sometimes, when i move clockwise the encoder, the position (number) is the same. Maybe in 10 movements, 2 mistakes. And similar in counterclockwise.

I will test your code. Thanks a lot.


Code:
#include <Encoder.h>

Encoder myEnc(5, 6);

void setup() {
  Serial.begin(9600);
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();

  if (newPosition != oldPosition) {

          if( newPosition % 4 == 0) {     //for each 4 positions of encoder)

                if (newPosition > oldPosition){
                     Serial.print(newPosition);
                     Serial.println(" - Left");
                     Joystick.button(5,1);
                     Joystick.button(6,0);
                 } 

                 else {
                      Serial.print(newPosition);
                      Serial.println(" - Right");
                      Joystick.button(5,0);
                      Joystick.button(6,1);
                 }
           }
           oldPosition = newPosition;
           
  } else {   //encoder same position
           Joystick.button(5,0);
           Joystick.button(6,0);
   }

Joystick.send_now();



}
 
Last edited:
Back
Top