Rotary encoder freeze or skipping , OLED and rotary.h

Hi,

i am doing a project for pulse control , i hit a road block where my rotary encoder gets freazed or skips in one of the menu pages. so i stripped the code to the bare minimum to troubleshoot the issue. i found out by adding the oled display code is the cause. so by deleting the code related to printing the result and use the serial monitor for debugging the rotary just works perfectly. i have searched many forums and but none have the issue i have.

please help

library used for rotary : GitHub - brianlow/Rotary: Rotary encoder library for Arduino

the code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Rotary.h>

Rotary r = Rotary(2, 4); // digital Pin attached to the rotary
Adafruit_SSD1306 display(128, 64, &Wire, 4); //  oled library


int pulse = 0;


void setup() {
  Serial.begin(9600);
  r.begin(true);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)

}

void loop() {


  //the display code, if added will make the rotatry skips or gets stuck

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0, 20);
  display.print("Test:");
  display.print(pulse);
  display.display();


  //the code below , the Rotary working fine and printing to the serial monitor with no issue


  unsigned char result = r.process();
  if (result == DIR_CCW)

  { if (pulse < 255)

    { pulse = pulse + 5;
      Serial.println(pulse);
    }
  }

  if (result == DIR_CW)
  {

    { if (pulse > 1)
      { pulse = pulse - 5;
        Serial.println(pulse);
      }
    }
  }
}

Rotary_oled.ino (1.07 KB)

first step to get help in the forum is to learn how to re-edit your post so code appears as a code-section

quickest way to insert code as a code section. Follow this link to get an instruction how to write an good first posting in just one minute or an even impressive first posting in just 10 minutes

just 3 mouseclicks and 4 keystrokes to make an good/impressive first posting

best regards Stefan

StefanL38: first step to get help in the forum is to learn how to re-edit your post so code appears as a code-section

quickest way to insert code as a code section. Follow this link to get an instruction how to write an good first posting in just one minute or an even impressive first posting in just 10 minutes

just 3 mouseclicks and 4 keystrokes to make an good/impressive first posting

ok there you go , now can i get my question answered or help diagnose the issue

Adafruit_SSD1306 display(128, 64, &Wire, 4); //  oled library

What is the last parameter in the constructor ?

UKHeliBob: Adafruit_SSD1306 display(128, 64, &Wire, 4); //  oled library

What is the last parameter in the constructor ?

this is the OLED reset

this is the OLED reset

So it doesn't relate to an Arduino pin ?

UKHeliBob: So it doesn't relate to an Arduino pin ?

Not at all i even switched pin 4 for the rotary to a different one , same issue with skipping

If the OLED reset pin is not used, you should not specify it in the setup. It will default to -1 (not used)

You should also time how long it takes to do all of your display functions. i2c isn’t that fast compared to spi so you are just busy doing other things and miss some rotary pulses. You certainly do not need to call all of those display functions every time through loop.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Rotary.h>

Rotary r = Rotary(2, 4); // digital Pin attached to the rotary
Adafruit_SSD1306 display(128, 64, &Wire); //  oled library


int pulse = 0;


void setup() {
  Serial.begin(9600);
  r.begin(true);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0, 20);
  display.print("Test:");
  display.print(pulse);
  display.display();

}
void timeIt( int count, void (*func)() ) {
  unsigned long startTime = micros();
  for( int i=0; i<count; ++i ) {
    func();
  }
  Serial.println( (micros() - startTime)/count );
}

void loop() {
  int count = 10;
  timeIt(count, loop1);
  timeIt(count, loop2);
  timeIt(count, loop3);
  while(1);
}

void loop1() {

  //just rotary testing

  //the code below , the Rotary working fine and printing to the serial monitor with no issue


  unsigned char result = r.process();
  if (result == DIR_CCW)

  { if (pulse < 255)

    { pulse = pulse + 5;
      Serial.println(pulse);
    }
  }

  if (result == DIR_CW)
  {

    { if (pulse > 1)
      { pulse = pulse - 5;
        Serial.println(pulse);
      }
    }
  }
}

void loop2() {

  //the display code, if added will make the rotatry skips or gets stuck

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0, 20);
  display.print("Test:");
  display.print(pulse);
  display.display();


  //the code below , the Rotary working fine and printing to the serial monitor with no issue


  unsigned char result = r.process();
  if (result == DIR_CCW)

  { if (pulse < 255)

    { pulse = pulse + 5;
      Serial.println(pulse);
    }
  }

  if (result == DIR_CW)
  {

    { if (pulse > 1)
      { pulse = pulse - 5;
        Serial.println(pulse);
      }
    }
  }
}

void loop3() {

  //minimized display code

  display.setCursor(5, 20);
  display.print(pulse);
  display.display();

  //the code below , the Rotary working fine and printing to the serial monitor with no issue


  unsigned char result = r.process();
  if (result == DIR_CCW)

  { if (pulse < 255)

    { pulse = pulse + 5;
      Serial.println(pulse);
    }
  }

  if (result == DIR_CW)
  {

    { if (pulse > 1)
      { pulse = pulse - 5;
        Serial.println(pulse);
      }
    }
  }
}

blh64:
You should also time how long it takes to do all of your display functions. i2c isn’t that fast compared to spi so you are just busy doing other things and miss some rotary pulses. You certainly do not need to call all of those display functions every time through loop.

thank you for the reply

minimizing the display code did not resolve the issue at all. but while looking at your code it gave me an idea in which i insert the display code inside the IF function and whalla, the encoder worked like a charm.

But,

one issue, this a code is a part of a menu and when i reach to the pulse menu, the screen goes black until i move the encoder and the info will appear. and i cannot have the static info in the setup void because it will mess-up the menu for other functions.

my observation:

  • if you add any code out side the IF function will freeze the rotary (not just the display code).
  • i do not have the issue with the other menu only with the rotary encoder could this be a rotary library issue ?
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Rotary.h>

Rotary r = Rotary(2, 4); // digital Pin attached to the rotary
Adafruit_SSD1306 display(128, 64, &Wire); //  oled library


int pulse = 0;


void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  r.begin(true);

}

void loop() {

  //minimized display code

  unsigned char result = r.process();
  if (result == DIR_CCW)

  { if (pulse < 255)

    { pulse = pulse + 5;
      Serial.println(pulse);
      display.setCursor(5, 20);
      display.clearDisplay();
      display.setTextColor(WHITE);
      display.setTextSize(2);
      display.setCursor(0, 20);
      display.print("Test:");
      display.print(pulse);
      display.display();
    }
  }

  if (result == DIR_CW)
  {

    { if (pulse > 1)
      { pulse = pulse - 5;
        Serial.println(pulse);
        display.clearDisplay();
        display.setTextColor(WHITE);
        display.setTextSize(2);
        display.setCursor(0, 20);
        display.print("Test:");
        display.print(pulse);
        display.display();
      }
    }
  }
}