Scrolling Text on SSD1306 OLED Screen

Hi everyone,

Sorry if this is really well documented anywhere, but how do you scroll text on SSD1306 OLED display using ESPHome. I am able to display information easily on the screen but it’s not very useful as due to the size of the screen you can’t fit too much text on there. So is there a way to scroll text if it’s too long to fit on the screen?

Thank you for your help and guidance I really appreciate it.
Rich

Unfortunately not, as it’s buffer is just big enough to handle the screen size data at once.
However,you can scroll the text or images on the screen (from side to side), but scrolling outside the screen is impossible, afaik.

1 Like

Thank you :slight_smile:

1 Like

On espeasy scrolling is possible on this lcd… So why isn’t possible on esphome.

1 Like

As far as I could understand the “scrolling” in espeasy is not actually scrolling. As it isn’t natively supported, someone made a plugin, which he claims it supports scrolling, but it isn’t actual scrolling. It’s more like turning pages (instead of fixed 8 lines it shows two lines at the time and the 4 screens are switching inbetween - it’s slideshow, not scroll).

The actual scrolling we are talking about here is like this one and afaik is not supported by the screen.

Would be interested in this too.
Theoretically if you have a sensor with text and the correct lambda function / code this should be possible to be simulated :wink:
But I am not good enough for this C magic :wink: perhaps someone has an idea to grab text, cut in in pieces and just refreshes the screen with new text every x seconds.

But seems someone came up with a solution for LCD displays, haven’t tried it but perhaps this could make the trick

1 Like

It would be possible to simulate, but only as a character by character scroll (which looks at least a bit choppy and not really smooth even when using a monospace font) - pixel by pixel scroll is still impossible.
Unfortunately I’m also not a coder, so even such a solution is out of my hands.

Well, tried anyway, at least on conceptual level (character scrolling, not pixel) :slight_smile:
Basic concept: determine text lentgh, print out the text (whatever fits on the screen), clip off the first letter and repeat until clipped to zero with a delay of 333ms between each print.

Unfortunately this code doesn’t work (don’t know why - it just prints out all texts at once one over another and makes an unreadable CF), but maybe someone else will be able to edit it in a way, that it would work.

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: GPIO0
    address: 0x3C
    lambda: |-
        std::string str="This is a scrolling text...";
        int length = str.length();
        it.print(0, 0, id(myfont), str.c_str());
        int i = 1;
        while (i < length) {
          delay(333);
          str.replace(0,1,"");
          it.print(0, 0, id(myfont), str.c_str());
          i++;
          
        }

Well, in case someone is still interested, it took some time, but i managed to simulate it (a bit clumsy) like this:

globals:
   - id: coords
     type: int
     restore_value: no
     initial_value: '0'
   - id: length
     type: int
     restore_value: no
     initial_value: '0'
interval:
  - interval: 50ms
    then:
        lambda: |-
            if (id(coords) < -(id(length))) {
             id(coords) = 0;
                }
            else  {
               id(coords) -= 2;
            }
font:
  - file: "ubuntuc.ttf"
    id: myfont
    size: 32
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x32"
    update_interval: 50ms
    scan: true
    lambda: |-
        std::string printout="This is a pretty large scrolling text...";
        int clength = printout.length();
        id(length)=clength*25 
     # multiplication factor (in this case 25) to be determined with trial and error based on your font width - used to reset coords to 0, when text scrolls out of display completely
        it.print(id(coords), 0, id(myfont), printout.c_str());;
        }

Replace the printout string with whatever you want to display, adjust your font and determine the multiplication factor (easier for monospace fonts) and that should do the trick.

4 Likes

superb! it’s working for me :slight_smile: Thank you.

I’m trying to put static icon (15px width) starting of (0,0) coordinate. But scrolling text overlapping to icon.

It’s starting next to icon after 2 pixel, but when scrolling is start, overlapping. How can i get rid off overlapping?

thank you

1 Like

Here is an example to scroll text smoothly (pixel wise) on a OLED or LED display.

globals:
   - id: scroll_x
     type: int
     restore_value: no
     initial_value: '0'
   - id: scroll_lenght
     type: int
     restore_value: no
     initial_value: '0'
- interval: 50ms
    then:
      if:
         condition:
           lambda: 'return id(page_counter) <= 4;'
         then:
           - component.update: watchface
           - lambda: |-
               if (id(scroll_x) < -(id(scroll_lenght))) {
                 // Start at right side of clipping area
                 id(scroll_x) = 210; 
               }
               else  {
                 id(scroll_x) -= 2;
               }
display:
  - platform: ili9xxx
    model: GC9A01A 
    id: watchface
    #example display

    pages:
      - id: page1 # Weather today
        lambda: |-
          auto grey = Color(140, 140, 140);

          it.start_clipping(30, 40, 210, 90);
              std::string printout=id(YOUR TEXT FROM A TEXT SENSOR).state.c_str();
              int clength = printout.length();
              id(scroll_lenght) = clength * 10;
              // multiplication factor (in this case 10) to be determined with trial and error based on your font width
              it.print(id(scroll_x), 50, id(font_24), grey, printout.c_str());
          it.end_clipping();