From 9b46ccdeca7afa4c157212f243db1d5f5c3d4dc6 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 2 Feb 2018 11:33:15 +0100 Subject: [PATCH] new encoder try --- src/main.cpp | 12 +++++----- src/rotary.cpp | 61 +++++++++++++++++++++++++++++++++----------------- src/rotary.h | 9 ++++++-- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a64b396..3dfac37 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,12 +8,12 @@ * GND O O GND * 5V O O 5V * 3V3 O O 3V3 - * GND O < 36 + * GND O < 36 only input, no pullups * RX * * 17 - * TX * < 38 ROTARY_A - * RST * BUTTON < 39 ROTARY_B - * 0 * BUTTON < 34 - * 22 * < 35 + * TX * < 38 ROTARY_A only input, no pullups + * RST * BUTTON < 39 ROTARY_B only input, no pullups + * 0 * BUTTON < 34 only input, no pullups + * 22 * < 35 only input, no pullups * BME280_SDO 19 * LoRa_MISO ? * 32 * BME280_CS 23 * ? * 33 * 18 x LoRa_CS * 25 MAX98_DIN @@ -313,5 +313,5 @@ void loop() u8g2.sendBuffer(); // bme280.printValues(); - delay(100); + delay(200); } diff --git a/src/rotary.cpp b/src/rotary.cpp index 61d78b9..99c2386 100644 --- a/src/rotary.cpp +++ b/src/rotary.cpp @@ -1,13 +1,5 @@ /* interrupt routine for Rotary Encoders - tested with Noble RE0124PVB 17.7FINB-24 http://www.nobleusa.com/pdf/xre.pdf - available at pollin.de - and a few others, seems pretty universal - - The average rotary encoder has three pins, seen from front: A C B - Clockwise rotation A(on)->B(on)->A(off)->B(off) - CounterCW rotation B(on)->A(on)->B(off)->A(off) - - and may be a push switch with another two pins, pulled low at pin 8 in this case - raf@synapps.de 20120107 + idea from: https://github.com/marcmerlin/IoTuz/blob/95f53be6569c68f7fbef491bb36082870f82d629/IoTuz.cpp */ @@ -15,7 +7,11 @@ //using namespace std; -Rotary::Rotary() {} +Rotary* Rotary::instance = NULL; + +Rotary::Rotary() { + instance = this; +} bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) { this->pinA = pinA; @@ -25,9 +21,6 @@ bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) { pinMode(pinB, INPUT_PULLUP); pinMode(pinButton, INPUT_PULLUP); - encoder = new ClickEncoder(pinA, pinB, pinButton, 4); - //encoder->setButtonOnPinZeroEnabled(true); - xTaskCreate( &cTaskWrapper, /* Task function. */ "encoderTask", /* String with name of task. */ @@ -35,6 +28,10 @@ bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) { this, /* Parameter passed as input of the task */ tskIDLE_PRIORITY+2, /* Priority of the task. */ &taskHandle); /* Task handle. */ + + attachInterrupt(digitalPinToInterrupt(pinA), doEncoder, CHANGE); + attachInterrupt(digitalPinToInterrupt(pinB), doEncoder, CHANGE); + return true; } @@ -43,14 +40,13 @@ void Rotary::cTaskWrapper(void* parameters) { } void Rotary::task(void *pvParameters) { + xTaskToNotify = xTaskGetCurrentTaskHandle(); + uint32_t ulNotificationValue; while(true) { - encoder->service(); - value += encoder->getValue(); - if (value != last) { - last = value; - if (callback) callback(value); - } - vTaskDelay(1 / portTICK_PERIOD_MS); + ulNotificationValue = ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); + int newPos = encoderPos/2; + if (lastPos != newPos) + if (callback) callback(newPos); } vTaskDelete(NULL); } @@ -59,3 +55,28 @@ bool Rotary::registerCallback(std::function callback) { this->callback = callback; return true; } + +// Interrupt on changing state +void Rotary::doEncoder() { + if ((millis() - instance->debounceMillis) > instance->debounceDelay) { + instance->debounceMillis = millis(); + + 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 ); + vTaskNotifyGiveFromISR( instance->xTaskToNotify, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} diff --git a/src/rotary.h b/src/rotary.h index 209b58f..916602e 100644 --- a/src/rotary.h +++ b/src/rotary.h @@ -17,8 +17,13 @@ class Rotary { Rotary(); bool begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton); bool registerCallback(std::function callback); - ClickEncoder *encoder; - int16_t last, value; + static void IRAM_ATTR doEncoder(void); + static Rotary* instance; + volatile int encoderPos = 0; + int lastPos = 0; + uint32_t debounceMillis; + uint32_t debounceDelay = 1; + TaskHandle_t xTaskToNotify; private: uint8_t pinA; uint8_t pinB;