Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple software de-bounce in RotaryEncoder::_encoder_ISR() #4

Open
martind69 opened this issue Feb 18, 2024 · 1 comment
Open

Simple software de-bounce in RotaryEncoder::_encoder_ISR() #4

martind69 opened this issue Feb 18, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@martind69
Copy link

martind69 commented Feb 18, 2024

Hi, i had a problem with bouncy china knob's

maybe you can update your code like this. I copied from RotaryEncoder::_button_ISR() and changed to micros()

void ARDUINO_ISR_ATTR RotaryEncoder::_encoder_ISR()
{
  /**
   * Almost all of this came from a blog post by Garry on GarrysBlog.com:
   * https://garrysblog.com/2021/03/20/reliably-debouncing-rotary-encoders-with-arduino-and-esp32/
   *
   * Read more about how this works here:
   * https://www.best-microcontroller-projects.com/rotary-encoder.html
   */

  static uint8_t _previousAB = 3;
  static int8_t _encoderPosition = 0;
  static unsigned long _lastInterruptTime = 0;
  static long _stepValue;
  bool valueChanged = false;

  // Simple software de-bounce
  if( ( micros() - _lastInterruptTime ) < 100 )
    return;

  _previousAB <<= 2;  // Remember previous state

  if( digitalRead( encoderPinA ) ) _previousAB |= 0x02; // Add current state of pin A
  if( digitalRead( encoderPinB ) ) _previousAB |= 0x01; // Add current state of pin B

  _encoderPosition += encoderStates[( _previousAB & 0x0f )];


  /**
   * Based on how fast the encoder is being turned, we can apply an acceleration factor
   */

  unsigned long speed = micros() - _lastInterruptTime;

  if( speed > 40000 )                              // Greater than 40 milliseconds
    _stepValue = this->stepValue;                  // Increase/decrease by 1 x stepValue

  else if( speed > 20000 )                         // Greater than 20 milliseconds
    _stepValue = ( this->stepValue <= 9 ) ?        // Increase/decrease by 3 x stepValue
      this->stepValue : ( this->stepValue * 3 )    // But only if stepValue > 9
    ;

  else                                             // Faster than 20 milliseconds
    _stepValue = ( this->stepValue <= 100 ) ?      // Increase/decrease by 10 x stepValue
      this->stepValue : ( this->stepValue * 10 )   // But only if stepValue > 100
    ;


  /**
   * Update counter if encoder has rotated a full detent
   * For the following comments, we'll assume it's 4 steps per detent
   * The tripping point is `STEPS - 1` (so, 3 in this example)
   */

  if( _encoderPosition > encoderTripPoint )        // Four steps forward
  {
    this->currentValue += _stepValue;
    valueChanged = true;
  }
  else if( _encoderPosition < -encoderTripPoint )  // Four steps backwards
  {
    this->currentValue -= _stepValue;
    valueChanged = true;
  }

  if( valueChanged )
  {
    encoderChangedFlag = true;

    // Reset our "step counter"
    _encoderPosition = 0;

    // Remember current time so we can calculate speed
    _lastInterruptTime = micros();
  }
}
@MaffooClock MaffooClock self-assigned this Jan 23, 2025
@MaffooClock
Copy link
Owner

My apologies for letting this get cold!

So you're proposing the following patch:

--- ESP32RotaryEncoder.cpp	2025-01-23 08:49:43
+++ ESP32RotaryEncoder-changed.cpp	2025-01-23 08:56:51
@@ -328,11 +328,14 @@
   static int8_t _encoderPosition = 0;
   static unsigned long _lastInterruptTime = 0;
   static long _stepValue;
-
   bool valueChanged = false;

-  _previousAB <<=2;  // Remember previous state
+  // Simple software de-bounce
+  if( ( micros() - _lastInterruptTime ) < 100 )
+    return;

+  _previousAB <<= 2;  // Remember previous state
+
   if( digitalRead( encoderPinA ) ) _previousAB |= 0x02; // Add current state of pin A
   if( digitalRead( encoderPinB ) ) _previousAB |= 0x01; // Add current state of pin B

\ No newline at end of file
@@ -343,12 +346,12 @@
    * Based on how fast the encoder is being turned, we can apply an acceleration factor
    */

-  unsigned long speed = millis() - _lastInterruptTime;
+  unsigned long speed = micros() - _lastInterruptTime;

-  if( speed > 40 )                                 // Greater than 40 milliseconds
+  if( speed > 40000 )                              // Greater than 40 milliseconds
     _stepValue = this->stepValue;                  // Increase/decrease by 1 x stepValue

-  else if( speed > 20 )                            // Greater than 20 milliseconds
+  else if( speed > 20000 )                         // Greater than 20 milliseconds
     _stepValue = ( this->stepValue <= 9 ) ?        // Increase/decrease by 3 x stepValue
       this->stepValue : ( this->stepValue * 3 )    // But only if stepValue > 9
     ;
\ No newline at end of file
@@ -384,6 +387,6 @@
     _encoderPosition = 0;

     // Remember current time so we can calculate speed
-    _lastInterruptTime = millis();
+    _lastInterruptTime = micros();
   }
 }
\ No newline at end of file

...appears to be reasonable enough. I'll commit this change after I've tested.

@MaffooClock MaffooClock added the enhancement New feature or request label Jan 23, 2025
@MaffooClock MaffooClock added this to the v1.1.1 milestone Jan 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants