Using Rotary Encoders EC11 with joystick

So i'm using 5 rotary encoders EC11 to make a autopilot panel for MFS.

I alredy have the push buttons working in another arduino but i can't read and press the rotary encoders in this one. I have the 5 connect to arduino pro micro, but only one work.

the wiring is the midle pin is connect to GND and the other 2 (A and B) are connect to 2 diferent digital pins.

rotary1 - pins 2 and 3
rotary2 - pins 4 and 5
rotary2 - pins 6 and 7
rotary2 - pins 16 and 10
rotary2 - pins 15 and 14

I'm using Joystick library from Matthew Heironimus (GitHub - MHeironimus/ArduinoJoystickLibrary: An Arduino library that adds one or more joysticks to the list of HID devices an Arduino Leonardo or Arduino Micro can support.) as well the "RotaryEncoder" library by Matthias Hertel

the code i already have is:

Bloco de Citação

#include <RotaryEncoder.h>
#include <Joystick.h>

#define rotIntPin0 3
#define rotIntPin1 2
#define rotIntPin2 4
#define rotIntPin3 5
#define rotIntPin4 6
#define rotIntPin5 7
#define rotIntPin6 8
#define rotIntPin7 9
#define rotIntPin8 10
#define rotIntPin9 12


//Define Encoders
RotaryEncoder encoder(rotIntPin0,rotIntPin1);
RotaryEncoder encoder2(rotIntPin3,rotIntPin2);
RotaryEncoder encoder3(rotIntPin4,rotIntPin5);
RotaryEncoder encoder4(rotIntPin6,rotIntPin7);
RotaryEncoder encoder5(rotIntPin9,rotIntPin8);

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
  10, 0,                  // Button Count, Hat Switch Count
  false, false, false,     // X and Y, but no Z Axis
  false, false, false,   // No Rx, Ry, or Rz
  false, false,          // No rudder or throttle
  false, false, false);  // No accelerator, brake, or steering

void setup() {
  

  Joystick.begin(false);
  attachInterrupt(digitalPinToInterrupt(rotIntPin0), getTick1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin1), getTick1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin2), getTick2, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin3), getTick2, CHANGE); 
  attachInterrupt(digitalPinToInterrupt(rotIntPin4), getTick3, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin5), getTick3, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin6), getTick4, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin7), getTick4, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin8), getTick5, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotIntPin9), getTick5, CHANGE);
}

void getTick1(){
  encoder.tick();    
}
void getTick2(){
  encoder2.tick();
}
void getTick3(){
  encoder3.tick();    
}
void getTick4(){
  encoder4.tick();    
}
void getTick5(){
  encoder5.tick();    
}



void loop() {
    
   static int pos = 0;  
   static int pos2 = 0;
   static int pos3 = 0;
   static int pos4 = 0;
   static int pos5 = 0;  
    
   int newPos = encoder.getPosition();
   int newPos2 = encoder2.getPosition();
   int newPos3 = encoder3.getPosition();
   int newPos4 = encoder4.getPosition();
   int newPos5 = encoder5.getPosition();
   
   if (pos != newPos) {
    if (newPos < pos) Joystick.pressButton(0);
    else if (newPos > pos) Joystick.pressButton(1);
    pos = newPos;
   }   
   
   if (pos2 != newPos2) {
    if (newPos2 < pos2) Joystick.pressButton(2);
    else if (newPos2 > pos2) Joystick.pressButton(3);
    pos2 = newPos2;    
   } 

   if (pos3 != newPos3) {
    if (newPos3 < pos3) Joystick.pressButton(4);
    else if (newPos3 > pos3) Joystick.pressButton(5);
    pos3 = newPos3;
   } 

   if (pos4 != newPos4) {
    if (newPos4 < pos4) Joystick.pressButton(6);
    else if (newPos4 > pos4) Joystick.pressButton(7);
    pos4 = newPos4;
   } 

   if (pos5 != newPos5) {
    if (newPos5 < pos5) Joystick.pressButton(8);
    else if (newPos5 > pos5) Joystick.pressButton(9);
    pos5 = newPos5;
   } 
  
  Joystick.sendState();//send state 1st before we clear the button states
  ClearButtons();
}

void ClearButtons()
{
  delay(150);
  Joystick.releaseButton(0);
  Joystick.releaseButton(1);
  Joystick.releaseButton(2);
  Joystick.releaseButton(3);
  Joystick.releaseButton(4);
  Joystick.releaseButton(5);
  Joystick.releaseButton(6);
  Joystick.releaseButton(7);
  Joystick.releaseButton(8);
  Joystick.releaseButton(9);
   
}

From this page:

The Pro Micro has five external interrupts, which allow you to instantly trigger a function when a pin goes either high or low (or both). If you attach an interrupt to an interrupt-enabled pin, you'll need to know the specific interrupt that pin triggers: pin 3 maps to interrupt 0 (INT0), pin 2 is interrupt 1 (INT1), pin 0 is interrupt 2 (INT2), pin 1 is interrupt 3 (INT3), and pin 7 is interrupt 4 (INT6).

I think it might still work well enough with only one interrupt pin for each encoder, for example all the "A" pins. The "B" pins could be connected to non-interrupt digital pins. Let us know if that works well.

1 Like

ok thanks I will try

I've tried to make your code a bit shorter:

#include <RotaryEncoder.h>
#include <Joystick.h>

const byte rotEncoders = 5;
const byte rotPinA[rotEncoders] = {0, 1, 2, 3, 7}; //external interrupt pins
const byte rotPinB[rotEncoders] = {4, 5, 6, 8, 9}; //non-interrupt digital pins

//Define Encoders
RotaryEncoder encoder[rotEncoders];

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
  10, 0,                  // Button Count, Hat Switch Count
  false, false, false,     // X and Y, but no Z Axis
  false, false, false,   // No Rx, Ry, or Rz
  false, false,          // No rudder or throttle
  false, false, false);  // No accelerator, brake, or steering

void getTick0(){
  encoder[0].tick();    
}
void getTick1(){
  encoder[1].tick();
}
void getTick2(){
  encoder[2].tick();    
}
void getTick3(){
  encoder[3].tick();    
}
void getTick4(){
  encoder[4].tick();    
}

void setup() {

  Joystick.begin(false);

  void (*tickISR[rotEncoders]) () = {getTick0, getTick1, getTick2, getTick3, getTick4};

  for (byte e=0; e<rotEncoders; e++) {
    encoder[e] = RotaryEncoder(rotPinA[e], rotPinB[e]);
    attachInterrupt(digitalPinToInterrupt(rotPinA[e]), tickISR[e], CHANGE);
  }
}



void loop() {
    
   static int pos[rotEncoders];  

      
   int newPos[rotEncoders];

   for (byte e=0; e<rotEncoders; e++) {
     newPos[e] = encoder[e].getPosition();
   
     if (pos[e] != newPos[e]) {
       if (newPos < pos[e]) Joystick.pressButton(2*e);
       else Joystick.pressButton(2*e+1);
     pos[e] = newPos[e];
   }   
     
  Joystick.sendState();//send state 1st before we clear the button states
  ClearButtons();
}

void ClearButtons()
{
  delay(150);
  for (byte b= 0; b<rotEncoders*2; b++)
    Joystick.releaseButton(b);
}

that give me this error

no matching function for call to 'RotaryEncoder::RotaryEncoder()'

In other way, this is working exept the encoders connected to pins 0 and 1

#include <Encoder.h>
#include <Joystick.h>

Encoder myEnc1(7, 9);
Encoder myEnc2(1, 5);
Encoder myEnc3(2, 6);
Encoder myEnc4(3, 8);
Encoder myEnc5(7, 9);

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
  10, 0,                  // Button Count, Hat Switch Count
  false, false, false,     // X and Y, but no Z Axis
  false, false, false,   // No Rx, Ry, or Rz
  false, false,          // No rudder or throttle
  false, false, false);  // No accelerator, brake, or steering




void setup() {
  Joystick.begin(false);
}

long oldPosition1  = 0;
long oldPosition2  = 0;
long oldPosition3  = 0;
long oldPosition4  = 0;
long oldPosition5  = 0;

void loop() {
  long newPosition1 = myEnc1.read();
  if (newPosition1 != oldPosition1) {
    if (newPosition1 < oldPosition1) Joystick.pressButton(0);
    else if (newPosition1 > oldPosition1) Joystick.pressButton(1);
    oldPosition1 = newPosition1;
    
  }


  long newPosition2 = myEnc2.read();
  if (newPosition2 != oldPosition2) {
    if (newPosition2 < oldPosition2) Joystick.pressButton(2);
    else if (newPosition2 > oldPosition2) Joystick.pressButton(3);
    oldPosition2 = newPosition2;
    
  }

  long newPosition3 = myEnc3.read();
  if (newPosition3 != oldPosition3) {
    if (newPosition3 < oldPosition3) Joystick.pressButton(4);
    else if (newPosition3 > oldPosition3) Joystick.pressButton(5);
    oldPosition3 = newPosition3;
  }

  
  long newPosition4 = myEnc4.read();
  if (newPosition4 != oldPosition4) {
    if (newPosition4 < oldPosition4) Joystick.pressButton(6);
    else if (newPosition4 > oldPosition4) Joystick.pressButton(7);
    oldPosition4 = newPosition4;
  }


  long newPosition5 = myEnc5.read();
  if (newPosition5 != oldPosition5) {
    if (newPosition5 < oldPosition5) Joystick.pressButton(8);
    else if (newPosition5 > oldPosition5) Joystick.pressButton(9);
    oldPosition5 = newPosition5;
    
  }


  Joystick.sendState();//send state 1st before we clear the button states
  ClearButtons();
   
}


void ClearButtons()
{
  delay(150);
  Joystick.releaseButton(0);
  Joystick.releaseButton(1);
  Joystick.releaseButton(2);
  Joystick.releaseButton(3);
  Joystick.releaseButton(4);
  Joystick.releaseButton(5);
  Joystick.releaseButton(6);
  Joystick.releaseButton(7);
  Joystick.releaseButton(8);
  Joystick.releaseButton(9);
   
}

here i try use the library encoder.h from PaulStoffregen
library encoder.h

I can see why it is not working for the encoder connected to pin 0:

Encoder myEnc1(7, 9);
Encoder myEnc2(1, 5);
Encoder myEnc3(2, 6);
Encoder myEnc4(3, 8);
Encoder myEnc5(7, 9);

None of the encoders are using pin 0. But 2 of them are using pins 7, 9.

Ok, thanks. I change that and and now, when i rotate the encoders connected to pins 0/4 and 1/5 its ghosting

when I use the Serial.begin is this that appear:

  when 1,5 is connected:

image

  when 2,6 is connected:

image

Ah, yes. Try:

#include <RotaryEncoder.h>
#include <Joystick.h>

const byte rotEncoders = 5;
const byte rotPinA[rotEncoders] = {0, 1, 2, 3, 7}; //external interrupt pins
const byte rotPinB[rotEncoders] = {4, 5, 6, 8, 9}; //non-interrupt digital pins

//Define Encoders
RotaryEncoder* encoder[rotEncoders];

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
  10, 0,                  // Button Count, Hat Switch Count
  false, false, false,     // X and Y, but no Z Axis
  false, false, false,   // No Rx, Ry, or Rz
  false, false,          // No rudder or throttle
  false, false, false);  // No accelerator, brake, or steering

void getTick0(){
  encoder[0]->tick();    
}
void getTick1(){
  encoder[1]->tick();
}
void getTick2(){
  encoder[2]->tick();    
}
void getTick3(){
  encoder[3]->tick();    
}
void getTick4(){
  encoder[4]->tick();    
}

void setup() {

  Joystick.begin(false);

  void (*tickISR[rotEncoders]) () = {getTick0, getTick1, getTick2, getTick3, getTick4};

  for (byte e=0; e<rotEncoders; e++) {
    encoder[e] = new RotaryEncoder(rotPinA[e], rotPinB[e]);
    attachInterrupt(digitalPinToInterrupt(rotPinA[e]), tickISR[e], CHANGE);
  }
}



void loop() {
    
   static int pos[rotEncoders];
   int newPos[rotEncoders];

   for (byte e=0; e<rotEncoders; e++) {
     newPos[e] = encoder[e]->getPosition();
   
     if (pos[e] != newPos[e]) {
       if (newPos < pos[e]) Joystick.pressButton(2*e);
       else Joystick.pressButton(2*e+1);
       pos[e] = newPos[e];
    }
  }   
     
  Joystick.sendState();//send state 1st before we clear the button states
  ClearButtons();
}

void ClearButtons()
{
  delay(150);
  for (byte b= 0; b<rotEncoders*2; b++)
    Joystick.releaseButton(b);
}

now it compiled (it's missing une } before j "joystick.sendState();" ) but dont work. None of the encoders give state.

But that is no problem since now i can put 3 encoders working at the same time.

if i cannot put the two connected to pins 1 and 0 i will use one more encoder to do the job.

Thanks

Well spotted, thanks.

I'm sorry. Can anyone else see an error in my suggested code?

I don't understand how another encoder will fix that?

sorry, I want to mean another arduino pro. I have one in the project that have 3 pins available

Ok, got it.

I'm sorry, but I don't know why 2 of your 5 encoders are not working, either with your code or my suggested code. Maybe post some photos of the circuit? Please make sure they are as bright and clear as possible. Maybe I can spot something.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.