# TFT Graphics - Scrolling ruler scale tied to Enc position

**URL:** <https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129>\
**Category:** General Guidance\
**Created:** [February 22, 2026, 8:03am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129 "2026-02-22T08:03:48Z")\
**Posts on this page:** 12\
**Page:** 2

<div class="post-metadata">

**Author:** ![xfpd](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/xfpd/32/1120236_2.png) [@xfpd](https://forum.arduino.cc/u/xfpd)\
**Post date:** [February 26, 2026, 1:26am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/21 "2026-02-26T01:26:33Z")

</div>

> [@DucatiboyStu](#):
>
> enough code snippet to make it work

No. It was not.

---

<div class="post-metadata">

**Author:** ![sumguy](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sumguy/32/1134826_2.png) [@sumguy](https://forum.arduino.cc/u/sumguy)\
**Post date:** [February 26, 2026, 2:03am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/22 "2026-02-26T02:03:06Z")

</div>

@DucatiboyStu the Adafruit\_GFX library gives you access to a framebuffer called GFXcanvas that will give your animations a smooth and virtually flicker free scroll.

Your code can be adapted to the GFXcanvas quite easily, the example I posted uses a canvas framebuffer. Google Adafruit GFXcanvas and check it out, if you have future projects that use displays you wont regret it.

---

<div class="post-metadata">

**Author:** ![DucatiboyStu](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ducatiboystu/32/1126779_2.png) [@DucatiboyStu](https://forum.arduino.cc/u/DucatiboyStu)\
**Post date:** [February 26, 2026, 5:44am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/23 "2026-02-26T05:44:42Z")

</div>

The rest of the code is irrelevant. I am sure you could make it work if you really wanted to 😀

---

<div class="post-metadata">

**Author:** ![DucatiboyStu](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ducatiboystu/32/1126779_2.png) [@DucatiboyStu](https://forum.arduino.cc/u/DucatiboyStu)\
**Post date:** [February 26, 2026, 5:46am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/24 "2026-02-26T05:46:44Z")

</div>

Its going to run in 2 modes, 1 for position, and the other for feed ratebut I get what you mean

I will prob re-do it using TFT-eSpi lib

---

<div class="post-metadata">

**Author:** ![xfpd](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/xfpd/32/1120236_2.png) [@xfpd](https://forum.arduino.cc/u/xfpd)\
**Post date:** [February 26, 2026, 5:50am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/25 "2026-02-26T05:50:31Z")

</div>

> [@DucatiboyStu](#):
>
> rest of the code is irrelevant

Not if it is written poorly.

---

<div class="post-metadata">

**Author:** ![DucatiboyStu](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ducatiboystu/32/1126779_2.png) [@DucatiboyStu](https://forum.arduino.cc/u/DucatiboyStu)\
**Post date:** [February 26, 2026, 6:45am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/26 "2026-02-26T06:45:26Z")

</div>

Well, you can always re-write it 😎

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [February 26, 2026, 12:49pm UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/27 "2026-02-26T12:49:50Z")

</div>

Which rotary encoder library are you using? I can't seem to find the correct one to compile the code.  
What type of Arduino?

---

<div class="post-metadata">

**Author:** ![DucatiboyStu](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ducatiboystu/32/1126779_2.png) [@DucatiboyStu](https://forum.arduino.cc/u/DucatiboyStu)\
**Post date:** [February 27, 2026, 1:16am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/28 "2026-02-27T01:16:08Z")

</div>

Not sure how I found it, but works very well with the ky-040

> **[GitHub - ownprox/Rotary\_Encoder\_KY-040\_Fixed: This is a state version of reading a KY-040 for...](https://github.com/ownprox/Rotary_Encoder_KY-040_Fixed)**
>
> This is a state version of reading a KY-040 for Arduino, It offers full accuracy unlike other solutions.

---

<div class="post-metadata">

**Author:** ![DucatiboyStu](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ducatiboystu/32/1126779_2.png) [@DucatiboyStu](https://forum.arduino.cc/u/DucatiboyStu)\
**Post date:** [March 1, 2026, 12:52am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/29 "2026-03-01T00:52:54Z")

</div>

So I am onto v2 now. I have added a second mode to show feed rate. This uses a simple button to change modes.

I also decided to have ruler go the full width of the screen. I looks better and is more funcional

Also changed the way the ticks are drawn. Instead overwriting the old tick, I redraw the background then the new ticks as required in the “if” loop

```arduino
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7796S.h>
#include <RotaryEncoder.h>
#include <Fonts/FreeSansBoldOblique9pt7b.h>
#include <Fonts/FreeSansBoldOblique12pt7b.h>

#define display_CS 10
#define display_RST 8
#define display_DC 9
#define display_MOSI 11
#define display_CLK 13

#define feedzLed 1

#define BLACK 0x0000
#define GRAY 0x8410 //lGRAY = light gray, GREY = dark grey 16bit colour
#define GREY 0x632C
#define WHITE 0xFFFF
#define RED 0xF800
#define ORANGE 0xFCA0
#define YELLOW 0xFFE0
#define DENIM 0x4CBA
#define GREEN 0x07E0
#define DARKGREEN 0x2BE3
#define LIGHTGREEN 0x97F0
#define CYAN 0x07FF
#define AQUA 0x04FF
#define BLUE 0x001F
#define MAGENTA 0xF81F
#define PINK 0xF69A
#define GREYGREEN 0x2984

Adafruit_ST7796S display(display_CS, display_DC, display_MOSI, display_CLK, display_RST);
RotaryEncoder Rotary(&RotaryChanged, 2, 3, 28); // Pins 2 (DT), 3 (CLK), 28 (SW) - 28 is just a null number as the (SW) is not used

int mode = 0;
int feedzButt = 0;
int encCounter = 0;

long posn = -999;
long newposn;
int buttonState;
int lastButtonState = HIGH;
long lastDebounceTime = 0;
long debounceDelay = 10;

char buffermeas[10];
char bufferimp[10];
char bufferMMS[10];
char bufferRPM[10];

void RotaryChanged() {
  const unsigned int state = Rotary.GetState();
  if (state & DIR_CW)
    encCounter++;
  if (state & DIR_CCW)
    encCounter--;
}

void setup() {
  Serial.begin(9600);
  Serial.print(("Oih !"));
  display.init(74, 284, 0, 0, ST7796S_BGR); //screen size 74 x 284
  display.invertDisplay(1);
  display.fillScreen(BLACK);
  display.setRotation(1);
  display.setTextColor(WHITE);
  display.setCursor(80, 100);
  display.setTextSize(1);
  display.println("T.I.S.M"); // mum, we are serious. google it
  delay(500);
  pinMode(feedzButt, INPUT_PULLUP);
  display.fillScreen(GRAY);
}

void position() {
  display.fillTriangle(140, 15, 150, 5, 130, 5, RED);
  display.fillTriangle(140, 30, 150, 40, 130, 40, RED);
  display.drawRoundRect(0, 1, 284, 44, 10, RED);
  display.drawRoundRect(2, 2, 282, 42, 10, RED);
  display.drawRoundRect(3, 4, 279, 38, 10, RED);

  float measurment = (encCounter / 200.000);
  float imperial = (measurment / 2.5400);

  dtostrf(measurment, 6, 3, buffermeas);
  dtostrf(imperial, 6, 4, bufferimp);
  
  newposn = encCounter; // derived from rotary encoder

  if (newposn != posn) {
    posn = newposn;
    int16_t startX = (encCounter - 660); // zero maj posn to triangles
    int16_t startY = 8;
    int16_t numTicks = 200;
    int16_t minTickHeight = 10;
    int16_t medTickHeight = 20;
    int16_t majTickHeight = 30;
    int16_t minTickspacing = 20;
    int16_t medTickspacing = 100;
    int16_t majTickspacing = 200;
    display.fillRoundRect(4, 5, 278, 35, 10, WHITE);

    for (int i = 0; i < numTicks; i++) {
      display.drawFastVLine(startX + (i * minTickspacing), startY + 10, minTickHeight, BLACK);
      display.drawFastVLine(startX + (i * medTickspacing), startY, medTickHeight, BLACK);
      display.drawFastVLine(startX + (i * majTickspacing), startY, majTickHeight, BLACK);
    }
    display.fillRect(0, 45, 280, 40, GRAY);
    display.setTextColor(BLACK);
    display.setTextSize(1);
    display.setFont(&FreeSansBoldOblique12pt7b);
    display.setCursor(70, 65);
    display.print(buffermeas);
    display.setCursor(140, 65);
    display.print("mm");
    display.setCursor(195, 65);
    display.setFont(&FreeSansBoldOblique9pt7b);
    display.print(bufferimp);
    display.setCursor(260, 65);
    display.print("in");
  }
}
void feedrate() {
  float rpm = (encCounter / 10.00);
  float feed = (rpm / 60.0);
  dtostrf(rpm, 6, 1, bufferRPM);
  dtostrf(feed, 6, 2, bufferMMS);

  newposn = encCounter; // derived from rotary encoder
  if (newposn != posn) {
    posn = newposn;
    display.fillScreen(GRAY);
    display.drawRoundRect(1, 1, 204, 44, 11, RED);
    display.drawRoundRect(3, 2, 201, 42, 10, RED);
    display.drawRoundRect(5, 4, 198, 38, 9, RED);
    display.fillRoundRect(6, 5, 196, 36, 9, BLUE);

    display.setFont(&FreeSansBoldOblique12pt7b);
    display.setTextSize(1);
    display.setTextColor(RED);
    display.setCursor(210, 30);
    display.print("FEED");

    display.setTextColor(WHITE);
    display.setCursor(30, 30);
    display.print(bufferMMS);
    display.setCursor(100, 30);
    display.print("mm/s");

    display.setTextColor(BLACK);
    display.setCursor(30, 68);
    display.print(bufferRPM);
    display.setCursor(100, 68);
    display.print("RPM");
  }
}

void loop() {
  int reading = digitalRead(feedzButt);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == LOW) {
        mode++;
        if (mode > 1) { // Change to the last mode number you want
          mode = 0;
        }
        Serial.print("Mode changed to: ");
        Serial.println(mode);
      }
    }
  }
  lastButtonState = reading;
  switch (mode) {
    case 0:
      position();
      break;
    case 1:
      feedrate();
      break;
  }
}

```

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [March 1, 2026, 3:17am UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/30 "2026-03-01T03:17:20Z")

</div>

I may have missed where you mentioned it, what type arduino are you using?

Is there a reason you are using software SPI for the display? This runs much slower than hardware SPI?

```arduino
Adafruit_ST7796S display(display_CS, display_DC, display_MOSI, display_CLK, display_RST);

```

You might want to set the Arduino IDE preferences to show all warning, both versions of your code have a similar problem:

```arduino
/home/user/Arduino/scrollingRulerScaleV2/scrollingRulerScaleV2.ino:108:41: warning: iteration 164 invokes undefined behavior [-Waggressive-loop-optimizations]
       display.drawFastVLine(startX + (i * majTickspacing), startY, majTickHeight, BLACK);
                                         ^
/home/user/Arduino/scrollingRulerScaleV2/scrollingRulerScaleV2.ino:105:23: note: within this loop
     for (int i = 0; i < numTicks; i++) {
                       ^
```

---

<div class="post-metadata">

**Author:** ![DucatiboyStu](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ducatiboystu/32/1126779_2.png) [@DucatiboyStu](https://forum.arduino.cc/u/DucatiboyStu)\
**Post date:** [March 1, 2026, 12:25pm UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/31 "2026-03-01T12:25:32Z")

</div>

Uno/Pro mini/nano/Tennsy 4

I probably could use hardware SPI, but it was already there from recycled code

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [August 28, 2026, 12:26pm UTC](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129/32 "2026-08-28T12:26:11Z")

</div>

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

[Previous page](https://forum.arduino.cc/t/tft-graphics-scrolling-ruler-scale-tied-to-enc-position/1432129.md?page=1)
