Encoder Issues

Paul013

Member
Hi All
I have code for an encoder that works on an old ++2 and a new Teensy 4 but will not work on a 3.2. The pullups measure ok. I have tried various pins but still no joy. Is there a known issue when it comes to rotary encoders on 3.2 boards?
Regards,
Paul

Code:
#include <Encoder.h>
#include <USB-MIDI.h>

// Rotary Encoder pins
const int encoderPinA = 2;
const int encoderPinB = 3;
const int encoderButtonPin = 4;  // Optional if using the encoder button

// MIDI channel
const int midiChannel = 7;  // MIDI channels are 0-15, so channel 7 corresponds to MIDI channel 8

// Encoder object
Encoder myEncoder(encoderPinA, encoderPinB);

int lastEncoderValue = 0;
int currentNote = 60;  // Middle C

void setup() {
  // Initialize the encoder
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderButtonPin, INPUT_PULLUP);  // Optional if using the encoder button

  // Start MIDI communication
  usbMIDI.begin();
}

void loop() {
  // Read the encoder
  int newEncoderValue = myEncoder.read() / 4;  // Divide by 4 to reduce sensitivity

  if (newEncoderValue != lastEncoderValue) {
    // Determine the direction of rotation
    if (newEncoderValue > lastEncoderValue) {
      // Rotate clockwise: Note On
      sendMidiNoteOn(currentNote, 127);  // 127 is the maximum velocity
    } else {
      // Rotate counter-clockwise: Note Off
      sendMidiNoteOff(currentNote, 0);  // 0 velocity to indicate Note Off
    }

    // Update the last encoder value
    lastEncoderValue = newEncoderValue;
  }

  // Read the encoder button (if used)
  if (digitalRead(encoderButtonPin) == LOW) {
    // Handle the encoder button press
    // For example, you can change the note or send another MIDI message
  }

  // Delay for debounce (optional)
  delay(10);
}

void sendMidiNoteOn(byte note, byte velocity) {
  usbMIDI.sendNoteOn(note, velocity, midiChannel);
}

void sendMidiNoteOff(byte note, byte velocity) {
  usbMIDI.sendNoteOff(note, velocity, midiChannel);
}
 
Are you sure that the encoder is not working? Or could the problem be at the MIDI side?
Please delete #include <USB-MIDI.h>. It's not necessary.

Paul
 
Are you sure that the encoder is not working? Or could the problem be at the MIDI side?
Please delete #include <USB-MIDI.h>. It's not necessary.

Paul
Hi Paul
Thanks for the response. The encoder definitely works as I used the same one on the other two boards.
Paul.
 
To check if the hardware works you might use a simple test program which only checks the encoder part. I just tested the following on a Teensy 3.2 and it works without issue (note: it uses the EncoderTool library)

C++:
#include "Arduino.h"
#include "EncoderTool.h"
using namespace EncoderTool;

// Rotary Encoder pins
int encoderPinA      = 2;
int encoderPinB      = 3;
int encoderButtonPin = 4; // Optional if using the encoder button

PolledEncoder myEncoder;

void onValueChanged(int value, int delta)
{
    if (delta > 0)
        Serial.println("MidiNoteOn"); // can't test the midi stuff -> simulate
    else
        Serial.println("MidiNoteOff");
}

void onButtonChanged(int state)
{
    Serial.printf("Button state: %d\n", state); // no need to debounce, the lib uses Bounce2 internally
}

//----------------------------------------------

void setup()
{
    myEncoder.begin(encoderPinA, encoderPinB, encoderButtonPin);
    myEncoder.attachCallback(onValueChanged);
    myEncoder.attachButtonCallback(onButtonChanged);
}

void loop()
{
    myEncoder.tick(); // call tick as often as possible
}
 
To check if the hardware works you might use a simple test program which only checks the encoder part. I just tested the following on a Teensy 3.2 and it works without issue (note: it uses the EncoderTool library)

C++:
#include "Arduino.h"
#include "EncoderTool.h"
using namespace EncoderTool;

// Rotary Encoder pins
int encoderPinA      = 2;
int encoderPinB      = 3;
int encoderButtonPin = 4; // Optional if using the encoder button

PolledEncoder myEncoder;

void onValueChanged(int value, int delta)
{
    if (delta > 0)
        Serial.println("MidiNoteOn"); // can't test the midi stuff -> simulate
    else
        Serial.println("MidiNoteOff");
}

void onButtonChanged(int state)
{
    Serial.printf("Button state: %d\n", state); // no need to debounce, the lib uses Bounce2 internally
}

//----------------------------------------------

void setup()
{
    myEncoder.begin(encoderPinA, encoderPinB, encoderButtonPin);
    myEncoder.attachCallback(onValueChanged);
    myEncoder.attachButtonCallback(onButtonChanged);
}

void loop()
{
    myEncoder.tick(); // call tick as often as possible
}
Hi Luni
Yes your code works in the serial monitor so I guess the hardware is ok. So any idea why my code doesn't work? Like I said, it works fine on a Teensy 4 and ++2.
 
Maybe something with the interrupts. Wild guess: the T2 doesn't use interrupts on the pins you are using. T3 and T4 do. I don't know if the MIDI stuff also uses interrupts. Maybe some T3 specific clash?.
Just add your midi code to the example I gave you (replace the serial.prints by your midi code) and see what happens. (I'll be away for a couple of hours now...) But others can certainly help here as well if you can't get it going
 
Hooked up a Teensy 3.2 and rotary encoder.
Indeed the sketch didn't run.
Found that these 3 lines need to be deleted:
C++:
#include <USB-MIDI.h>

pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);

This MIDI monitor now correctly shows the rotary encoder action:

1722180912193.png


It's also wise to add this to the end of loop():
C++:
  // discard incoming MIDI messages ---------------------------------------------------------
  while (usbMIDI.read()) {
  }
See this page for more info.

Paul
 
Thanks so much Paul. Appreciate you looking at this. Anyone have any idea why it would work on a 4 and not a 3.2? Seems strange.
Paul.
 
Anyone have any idea why it would work on a 4 and not a 3.2? Seems strange.
Looked into Encoder.h. As far as I can tell INPUT_PULLUP is done while instantiating the Encoder object.
I guess the defining the pins again in setup() messes things up. But the finer details are beyond my knowledge.

Paul
 
Yeah I checked the voltages after deleting the pullups and there was still voltage there so the extra pullups aren't needed. It's weird though that the other 2 boards still work with them left in. Just one of those annoying things designed to trip you up and make you pull your hair out.
Paul
 
Back
Top