Anyone familiar with the REBL_UI MENU project on github?

Hi all. I am porting the REBL_UI (DELTA_G) project from Arduino (with LCD) to ESP32 (OLED OLED). The hardware consists of the ESP32, a rotary encoder and an SSD1306 OLED. I don't mind saying that the code is more complex than I am used to.

I have managed (after a LOT of work) to compile and uploaded the code for the REBL_UI project to an ESP32 DevkitC Ver4. It all seems to work correctly, except that the encoder count results are always positive and always 1. I would normally expect results of 1,2,3,4, after 4 right turns, and then 3, 2, 1, -1 after 4 left turns.

I've stared at, and played with, the code for over a week now - but, no joy. I would much appreciate any help given. Here is the relevant portions of the code.

BTW: I tried contacting the author at github, a little over a week now. No reply. I assume, at this time of year, a vacation is at fault.

// The library .H file in it's entirety

#ifndef REBLInterface_h
#define REBLInterface_h

#include "Arduino.h"
#include "pins_arduino.h"
#include "Defines.h"

void initInterface(uint8_t, uint8_t, uint8_t);  //, uint8_t);

void initButton(uint8_t);
void pollButton();
void clearButton();
boolean checkButton();
boolean checkButtonLongPress();
void readButton();
void buttonOn();
void buttonOff();
boolean isButtonOn();

void initEncoder(uint8_t, uint8_t);  //, uint8_t);

void encoderOn();
void encoderOff();
char checkRotaryEncoder();
void useRotaryEncoderASCII(char&);
boolean peekRotaryEncoder();
boolean isEncoderOn();


// The 2 functions, below, concern the using the results of the rotary encoder.


// comment from author
// call with mult == 0 allows only one step per call no matter how fast the encoder is turning
template<class T>
void useRotaryEncoder(T& var, int mult = 0)
{
  if (mult){
    var += (checkRotaryEncoder() * mult);
  } 
  else {
    int chek = checkRotaryEncoder();
    if (chek > 0) var += 1;
    if (chek < 0) var -= 1;
  }
}

template<class T>
void useRotaryEncoder(T& var, T mini, T maxi, int mult = 0)
{
  if (mult){
    var += (checkRotaryEncoder() * mult);
  } 
  else {
    int chek = checkRotaryEncoder();
    if (chek > 0) var += 1;
    if (chek < 0) var -= 1;
  }
  if (var > maxi){
    var = mini;
  } else if (var < mini) {
    var = maxi;
  }
  
}

#endif

Portions of the .cpp file

// These are the portions of the .cpp file having to do with the rotary counter.

// Please note the following:

volatile char encoderCounter; // the variable for the positive or negative count                                                        
                              // on the decoder is declared as a char
                                 
volatile byte *bReg;  //  this and the next variable are used in the 
                          //  ISR_encoder_handler() and initEncoder functions

byte bMask;   //  I DO NOT understand their functionality and have a gut
                  //  feeling that they (when used on the ESP32) acre causing
                  //  or contributing to the problem


void initEncoder(uint8_t pinA, uint8_t pinB) {  //, uint8_t pinB) {
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  bMask = digitalPinToBitMask(pinB);

   //   I ADDED (unsigned  char*) for ESP32
  *bReg = (unsigned char*) portInputRegister(digitalPinToPort(pinB)); 
  encoderInterrupt = digitalPinToInterrupt(pinA);
}

void encoderOn() {
  attachInterrupt(encoderInterrupt, ISR_encoder_handler, FALLING);
  encoderCounter = 0;
}


void ISR_encoder_handler() {  // Here only a plus result is returned 
                              // and it is always 1
  if (*bReg & bMask) {
    encoderCounter--;
  } else {
    encoderCounter++;
  }
}

char checkRotaryEncoder() {
  if (encoderIsOn) {
    cli();
    char retval = encoderCounter;
    encoderCounter = 0;
    sei();
    return retval;
  } else {
    return 0;
  }
}

in 95% of all cases the bug is that part of the code that was considered as "irrelevant"

Your complete code is relevant.

You have posted the *.h and the *.cpp-files but to what IO-pins did you connect what type of rotary-encoder?

If you want further help on this issue you have to post your code and links to the datasheet of your encoder

best regards Stefan

1 Like

ESP32 ISR need to be declared with the IRAM_ATTR attribute

void IRAM_ATTR ISR() {
  …

Might be easier to switch to an ESP encoder library supporting the native API

StepanL38: Thanks for your reply! The encoder is a Bourne PEC11R-4215F-S0012. I would have posted the entire code but, it's rather large and complex, with more than 10 libraries. So I thought better of it. That's why I named the thread "Anyone familiar with"

It's done, thanks. Same result :frowning:

And great code it is. I've been using your Disco_Doser for 7 or 8 years!. The doser is still going strong.

I assumed I would have problems with the port to ESP32, but I didn't realize some of the code is way above my pay grade. The fact that "encoderCounter" is declared as a char, confuses me to no end. Especially when I looked at how many functions relied on it, down the line.

As I mentioned above, the code compiles and the only lack in function I discovered is the response of the ISR. So I assume, in the end, it will be fine.

I've been considering that. Might be the easiest solution. There are some good libs available.

Well the functions (macros) exist so it will compile

I tried it. Whereas before, the ISR always returned 1; turning right or left. Now it returns 0. Hmmm...

If I wanted to try an ESP encoder library, where I could isolate the encoderCounter, would that be difficult to implement?

bReg = portInputRegister(digitalPinToPort(pinB));

wouldn't compile on Arduino until I added: (unsigned char*)

so:

bReg = (unsigned char*) portInputRegister(digitalPinToPort(pinB));

As far a I can tell, yes.

The thing about encoderCounter being a char. If that's changed will the be bad things happening later?

On classic esp32 you can check this one out

  1. Sorry for being dense. Which library do you mean?
  2. Never used github except as a source. I'll learn how to correctly create a fork and let you know. :blush:

Done.

Sounds good. Thanks.

I think I've confused everyone. Your code, with my ESR32 and OLED changes, has compiled and uploaded for about a week now.

Result:

  1. The initial menu displays correctly (OLED) with 4 lines.
  2. When encoder is turned, left or right, the menu advances to a higher index,
  3. Chosen functions (defined in the .ino) work (mostly) correctly.

When I integrate the ESP encoder lib, should I leave the encoderCounter variable
declared as char?

Thanks

Implementation of the encoder library seems pretty straight forward. I would assume the whole thing would be inside the REBLInterface library.

// This is from the library's example code

ESP32Encoder encoder;
 
void setup () { 
  encoder.attachFullQuad ( DT, CLK );
  encoder.setCount ( 0 );
}
 
void loop () {    
  long newPosition = encoder.getCount() / 2;
} 

The counter is a signed 64 bit integer.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.