PaulStoffregen / Encoder

Quadrature Encoder Library for Arduino
http://www.pjrc.com/teensy/td_libs_Encoder.html
540 stars 239 forks source link

wrong counting backwards #99

Open tappete opened 8 months ago

tappete commented 8 months ago

Hi Paul, I use your code without problems on an Arduino iot33 with rotary encoder but with a high resolution encoder I see the count is constant but this happens:

counting forward from 0 to 17750, when I go back I get 3050 (not 0) then if I go forward I get 20800 and when I go back I get 6100 and so on...

In practice when I go forward I have constant counts of 17750 impulses while backwards 14700 effectively always losing 3050 when I go back

This is my test code

#include <Arduino.h>                   
#include <wiring_private.h>
#include <Wire.h> 
#include <Adafruit_SH110X.h>    

#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>

int A = 2; 
int B = 3;

Encoder myEnc(A, B);

#define i2c_Address 0x3c //initialize with the I2C display addr 0x3C 

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1    //   QT-PY / XIAO
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {

    Wire.begin();

    delay(50);
    display.begin(i2c_Address, true); // Address 0x3C default
    display.clearDisplay();
}

long oldPosition  = -999;

void loop() {

    long newPosition = myEnc.read();
    if (newPosition != oldPosition) {
    oldPosition = newPosition;

    display.setTextSize(1);
    display.setTextColor(SH110X_WHITE);
    display.setCursor(0, 0);
    display.print("pos");
    display.setCursor(30, 0);
    display.println(oldPosition);

    display.display();
    display.clearDisplay();
  }
}

If I don't use 2 interrupts, the count is completely off.

With or without the "ENCODER OPTIMIZE INTERRUPTS" function the result changes little.

I don't know what it could depend on.

Thank you, Davide

bwalc0 commented 6 months ago

You are using multiple libraries with a high res encoder. The processor may not be able to handle both the precision of the encoder as well as the 4 other libraries. This isn't necessarily an issue in encoder.h as it's written in assembly, it's more likely the libraries you are using may not be optimised. I'd suggest getting it to a working state, then slowly adding your code back in.

If it is the processor, consider using 2 arduinos.

Also, look at the encoder documentation. You may need to add a debounce if it's too sensitive.

Hope this helps.

tappete commented 6 months ago

Thanks for the advice,

Now I have migrated the code to an Arduino Nano ESP32 dividing the work across 2 cores. Unfortunately I can't use "attachInterrupt" in my code that immediately crashes.

How can I solve it?

Thank you, Davide

bwalc0 commented 6 months ago

Hi Davide,

Does the example code "Basic" work? If so, slowly add your code to that until it crashes again. You should be able to figure out what it is from that.

Thanks, Ben

tappete commented 6 months ago

In fact with the basic code it doesn't crash

#include <Encoder.h>

volatile byte state = LOW;
const int boardLed = LED_BUILTIN;

Encoder myEnc(D3, D5);

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");

  pinMode(boardLed, OUTPUT);
  pinMode(2, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(2), blink, CHANGE);
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }

   digitalWrite(boardLed, state);
}

void blink() {
  state = !state;
}

there is something that does not depend on the "encoder" library

I'm continuing with the investigation

Thank you very much, Davide