Browse Source

optimize encoder

main
Hendrik Langer 7 years ago
parent
commit
fb36da5bce
  1. 43
      src/rotary.cpp

43
src/rotary.cpp

@ -5,6 +5,8 @@
#include "rotary.h" #include "rotary.h"
#include "freertos/task.h"
//using namespace std; //using namespace std;
Rotary* Rotary::instance = NULL; Rotary* Rotary::instance = NULL;
@ -43,16 +45,33 @@ void Rotary::task(void *pvParameters) {
xTaskToNotify = xTaskGetCurrentTaskHandle(); xTaskToNotify = xTaskGetCurrentTaskHandle();
uint32_t ulNotificationValue; uint32_t ulNotificationValue;
while(true) { while(true) {
ulNotificationValue = ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); ulNotificationValue = ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
delay(2); // wait until bounce settled
static uint8_t old_AB = 0;
// grey code
// http://hades.mech.northwestern.edu/index.php/Rotary_Encoder
// also read up on 'Understanding Quadrature Encoded Signals'
// https://www.pjrc.com/teensy/td_libs_Encoder.html
// another interesting lib: https://github.com/0xPIT/encoder/blob/arduino/ClickEncoder.cpp
static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
old_AB <<= 2;
old_AB |= ((digitalRead(pinB))?(1<<1):0) | ((digitalRead(pinA))?(1<<0):0);
encoderPos += ( enc_states[( old_AB & 0x0f )]);
ulNotificationValue = ulTaskNotifyTake( pdTRUE, 0 ); // clear pending notifications
debouncePulses++; debouncePulses++;
if (debouncePulses > 3) { if (debouncePulses > 3) { // update every 4 pulses
debouncePulses = 0; debouncePulses = 0;
if (encoderPos > encoderPosOld+1) value++; if (encoderPos > encoderPosOld+1) value++; // if the value has at least changed for 2
else if (encoderPos < encoderPosOld-1) value--; else if (encoderPos < encoderPosOld-1) value--;
else continue; else continue; // otherwise skip
encoderPosOld = encoderPos; encoderPosOld = encoderPos;
if (callback) callback(value); if (callback) callback(value);
} }
} }
vTaskDelete(NULL); vTaskDelete(NULL);
} }
@ -64,25 +83,9 @@ bool Rotary::registerCallback(std::function<void(int)> callback) {
// Interrupt on changing state // Interrupt on changing state
void Rotary::doEncoder() { void Rotary::doEncoder() {
if ((millis() - instance->debounceMillis) > instance->debounceDelay) {
instance->debounceMillis = millis();
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
static uint8_t old_AB = 0;
// grey code
// http://hades.mech.northwestern.edu/index.php/Rotary_Encoder
// also read up on 'Understanding Quadrature Encoded Signals'
// https://www.pjrc.com/teensy/td_libs_Encoder.html
// another interesting lib: https://github.com/0xPIT/encoder/blob/arduino/ClickEncoder.cpp
static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
old_AB <<= 2;
old_AB |= ((digitalRead(instance->pinB))?(1<<1):0) | ((digitalRead(instance->pinA))?(1<<0):0);
instance->encoderPos += ( enc_states[( old_AB & 0x0f )]);
configASSERT( instance->xTaskToNotify != NULL ); configASSERT( instance->xTaskToNotify != NULL );
vTaskNotifyGiveFromISR( instance->xTaskToNotify, &xHigherPriorityTaskWoken ); vTaskNotifyGiveFromISR( instance->xTaskToNotify, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} }
}

Loading…
Cancel
Save