luni64 / EncoderTool

The EncoderTool is a library to manage and read out rotary encoders connected either directly or via multiplexers to ARM based boards. Encoder push buttons are supported. Callback functions can be attached to encoder changes and button presses to allow for event driven applications
MIT License
48 stars 12 forks source link

Help adapting Encoder lib sketch to EncoderTool lib #3

Closed m-r-m-s closed 3 years ago

m-r-m-s commented 3 years ago

Hi @luni64,

I am a new coder and just starting to learn how to implement a rotary encoder with a button and trying to adapt the encoderTool library on this sketch:

#include <Encoder.h>

Encoder enc_one(12, 11);
int value; 

long enc_one_previous  = -999;
byte button_previous; 

void setup() {
  pinMode(2, INPUT_PULLUP); 
}

void loop() {
  value = enc_one.read();
  if(value > 127) {    enc_one.write(127);   }
  else if(value < 0) {    enc_one.write(0);  } 

  value = constrain(value, 0, 127);
  if (value != enc_one_previous) {    enc_one_previous = value;    usbMIDI.sendControlChange(1, value, 1);  }

  value = digitalRead(2); 
  if(value != button_previous) {    button_previous = value;    usbMIDI.sendControlChange(2, (1 - value) * 127, 1);    delay(3);  }
}

Using the examples in the EncoderTool library I came up with this sketch which is close but I still haven't gotten the button logic correct:

#include "EncoderTool.h"
using namespace EncoderTool;

PolledEncoder encoder; // Polling encoder, please call corresponding tick() functions as often as possible, e.g. in loop

const int pinA = 12; //encoder pin A
const int pinB = 11; // encoder pin B
const int pinBtn = 2; // encoder button pin

int value; 

long encoder_previous  = -999;
byte button_previous; 

void setup() {

  encoder.begin(pinA, pinB, pinBtn);
  encoder.setValue(0); // set the counter to a position
  encoder.setLimits(1, 127); // limits the count range to [1..127] add "true" arg e.g. enc.setLimits(1, 127, true) cyclic count range from [1...127] 

}

void loop() {

  encoder.tick();

  value = encoder.getValue();
  if (value != encoder_previous) {    encoder_previous = value;    usbMIDI.sendControlChange(1, value, 1);  }

  value = encoder.buttonChanged();
  if(value != button_previous) {    button_previous = value;    usbMIDI.sendControlChange(2, (1 - value) * 127, 1);}

}

In the 1st encoder sketch, it works as expected(Button is pressed = 127 and when released = 0). How do I implement this logic using the EncoderTool library?

In the EncoderTool version, the values are reversed(button pressed = 0 and when released =127) and duplicated for each button state (pressed and released).

Any help is greatly appreciated. Thank you!

luni64 commented 3 years ago

You got the button value wrong you need to call getButton() if you want to read the button value. buttonChanged() returns 1 if the button changed and 0 if there was no change.

Below a working version. Since I dont have MIDI I replaced your MIDI calls by printouts. You also need to change the pin definitions back to your setup.

#include "EncoderTool.h"
using namespace EncoderTool;

PolledEncoder encoder; // Polling encoder, please call corresponding tick() functions as often as possible, e.g. in loop

const int pinA   = 0; //encoder pin A
const int pinB   = 1; // encoder pin B
const int pinBtn = 2; // encoder button pin

void setup()
{
    encoder.begin(pinA, pinB, pinBtn);
    encoder.setValue(1);       // set the counter to a position
    encoder.setLimits(1, 127); // limits the count range to [1..127] add "true" arg e.g. enc.setLimits(1, 127, true) cyclic count range from [1...127]
}

void loop()
{
    encoder.tick();

    if (encoder.valueChanged())
    {
        int value = encoder.getValue();
        Serial.printf("usbMIDI.sendControlChange(1,%d,1);\n", value);
        //usbMIDI.sendControlChange(1, value, 1);
    }

    if (encoder.buttonChanged())
    {
        int value = encoder.getButton();
        Serial.printf("usbMIDI.sendControlChange(2,%d,1);\n", (1 - value) * 127);
    }
}

prints out: image

m-r-m-s commented 3 years ago

@luni64 thank you so much for explaining and clarifying the button calls for me.

This now works with MIDI as expected. Brilliant work on this library. It works really well in this context. I am using a Teensy LC at the moment but hope to eventually use the SeeedStudio XIAO which looks like it is working in the dev branch here...

luni64 commented 3 years ago

XIAO compatibility is work in progress. Currently the interrupt based Encoders work, more soon