Browse Source

use RotaryEncoder library

main
Hendrik Langer 7 years ago
parent
commit
f6b980ff43
  1. 1
      platformio.ini
  2. 112
      src/rotary.cpp
  3. 25
      src/rotary.h

1
platformio.ini

@ -28,4 +28,5 @@ lib_deps =
https://github.com/Gianbacchio/ESP8266_Spiram.git https://github.com/Gianbacchio/ESP8266_Spiram.git
Adafruit Unified Sensor Adafruit Unified Sensor
Adafruit BME280 Library Adafruit BME280 Library
ClickEncoder
lib_ignore = ESPAsyncTCP lib_ignore = ESPAsyncTCP

112
src/rotary.cpp

@ -15,12 +15,7 @@
//using namespace std; //using namespace std;
TaskHandle_t Rotary::xTaskToNotify = NULL; Rotary::Rotary() {}
Rotary* Rotary::instance = NULL;
Rotary::Rotary() {
instance = this;
}
bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) { bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) {
this->pinA = pinA; this->pinA = pinA;
@ -30,112 +25,37 @@ bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) {
pinMode(pinB, INPUT_PULLUP); pinMode(pinB, INPUT_PULLUP);
pinMode(pinButton, INPUT_PULLUP); pinMode(pinButton, INPUT_PULLUP);
encoder = new ClickEncoder(pinA, pinB, pinButton, 4);
//encoder->setButtonOnPinZeroEnabled(true);
xTaskCreate( xTaskCreate(
&cTaskWrapper, /* Task function. */ &cTaskWrapper, /* Task function. */
"buttonTask", /* String with name of task. */ "encoderTask", /* String with name of task. */
2048, /* Stack size in words. */ 1024, /* Stack size in words. */
this, /* Parameter passed as input of the task */ this, /* Parameter passed as input of the task */
tskIDLE_PRIORITY+2, /* Priority of the task. */ tskIDLE_PRIORITY+2, /* Priority of the task. */
&buttonTaskHandle); /* Task handle. */ &taskHandle); /* Task handle. */
return true; return true;
} }
void Rotary::cTaskWrapper(void* parameters) { void Rotary::cTaskWrapper(void* parameters) {
static_cast<Rotary*>(parameters)->button_task(NULL); static_cast<Rotary*>(parameters)->task(NULL);
} }
void Rotary::button_task(void *pvParameters) { void Rotary::task(void *pvParameters) {
xTaskToNotify = xTaskGetCurrentTaskHandle();
attachInterrupt(digitalPinToInterrupt(pinA), doEncoderA, RISING);
attachInterrupt(digitalPinToInterrupt(pinB), doEncoderB, RISING);
// attachInterrupt(digitalPinToInterrupt(pinButton), doButton, FALLING);
uint32_t ulNotificationValue;
uint32_t ulStatusValue;
while(true) { while(true) {
rotating = true; // reset the debouncer encoder->service();
value += encoder->getValue();
ulNotificationValue = xTaskNotifyWait(0x00, ULONG_MAX, &ulStatusValue, portMAX_DELAY ); if (value != last) {
last = value;
// if ( rotating ) delay (1); // wait a little until the bouncing is done if (callback) callback(value);
if( ulStatusValue == 1 ) {
// adjust counter + if A leads B
encoderPos += 1;
changed();
rotating = false; // no more debouncing until loop() hits again
} else if ( ulStatusValue == 2 ) {
// adjust counter -1 if B leads A
encoderPos -= 1;
changed();
rotating = false; // no more debouncing until loop() hits again
} else if ( ulStatusValue == 4 ) {
Button_set = digitalRead(pinButton);
if (! Button_set ) {
encoderPos = 0;
}
} }
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
void Rotary::changed() {
if (lastReportedPos != encoderPos) {
if (callback) callback(encoderPos);
lastReportedPos = encoderPos;
} }
vTaskDelete(NULL);
} }
bool Rotary::registerCallback(std::function<void(int)> callback) { bool Rotary::registerCallback(std::function<void(int)> callback) {
this->callback = callback; this->callback = callback;
return true; return true;
} }
void Rotary::doButton() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
configASSERT( xTaskToNotify != NULL );
uint32_t intrBits = 4;
xTaskNotifyFromISR( xTaskToNotify, intrBits, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
// Interrupt on A changing state
void Rotary::doEncoderA() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (instance->skipA) {
instance->skipA = false;
instance->debounceA = millis();
return;
}
if (!digitalRead(instance->pinB) && ((millis() - instance->debounceA) > instance->debounceDelay)) {
instance->debounceA = millis();
instance->skipB = true;
configASSERT( xTaskToNotify != NULL );
uint32_t intrBits = 1;
xTaskNotifyFromISR( xTaskToNotify, intrBits, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
// Interrupt on B changing state, same as A above
void Rotary::doEncoderB() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (instance->skipB) {
instance->skipB = false;
instance->debounceB = millis();
return;
}
if (!digitalRead(instance->pinA) && ((millis() - instance->debounceB) > instance->debounceDelay)) {
instance->debounceB = millis();
instance->skipA = true;
configASSERT( xTaskToNotify != NULL );
uint32_t intrBits = 2;
xTaskNotifyFromISR( xTaskToNotify, intrBits, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}

25
src/rotary.h

@ -3,6 +3,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <functional> #include <functional>
#include <ClickEncoder.h>
// usually the rotary encoders three pins have the ground pin in the middle // usually the rotary encoders three pins have the ground pin in the middle
enum PinAssignments { enum PinAssignments {
@ -16,31 +17,15 @@ class Rotary {
Rotary(); Rotary();
bool begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton); bool begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton);
bool registerCallback(std::function<void(int)> callback); bool registerCallback(std::function<void(int)> callback);
static void IRAM_ATTR doEncoderA(void); ClickEncoder *encoder;
static void IRAM_ATTR doEncoderB(void); int16_t last, value;
static void IRAM_ATTR doButton(void);
static Rotary* instance;
static TaskHandle_t xTaskToNotify;
uint32_t debounceA;
uint32_t debounceB;
uint32_t debounceDelay = 50;
private: private:
volatile int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
boolean rotating = false; // debounce management
// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;
boolean Button_set = false;
boolean skipA = false;
boolean skipB = false;
uint8_t pinA; uint8_t pinA;
uint8_t pinB; uint8_t pinB;
uint8_t pinButton; uint8_t pinButton;
void changed(void);
std::function<void(int)> callback = nullptr; std::function<void(int)> callback = nullptr;
TaskHandle_t buttonTaskHandle; TaskHandle_t taskHandle;
void button_task(void*); void task(void*);
static void cTaskWrapper(void*); static void cTaskWrapper(void*);
}; };

Loading…
Cancel
Save