LCD I2C scrolling text from bottom to top

Hello,
I want to make something like this PewDiePie Live Subscriber Count - Livecounts but on the 16x2 I2C LCD.
Basically when there is a new subscriber let's say change from 100 to 101 last digit 0 will be slowly changed by upcoming 1 from the bottom. Can you help me how to do it. Because there must be for sure available library or function like scrollDisplayRight() but I don't want to scroll text in left or right directions but down and up/bottom to top.
Thanks!

To make characters scroll like that, you will have to create custom characters to simulate the current digit moving UP and the new digit moving in from the bottom. Look at the LiquidCrystal -> CustomCharacter example sketch to see how it is done.

Sorry to pour cold water on the idea but that is not going to work even with custom characters. In the first place the two rows characters are separated by a blank horizontal line. Secondly, there is a limit as to how many custom characters that you can create. You may be able to created enough to scroll a single digit up or down but certainly not if 2 different numbers need to be scrolled at the same time

If the hardware footprint is not an issue, for a few dollars/pounds more than the LCD, a TFT screen and an uno or mega may provide your solution.

Thanks for the reply, but Yes I can use TFT display and I'm not using LCD for money reason but for how they look like, so if it's possible I would like to stick to LCD and maybe try to play a bit with that custom character thing because I didn't heard about it before.

Good luck with the custom characters but you can only define 8 different ones.

When experimenting with them I hit on the idea of redefining them in the program but when a custom character is being displayed and you change its definition with the objective of using the new design the previously displayed character also changes to the new design.

Having said that, please let us know how you get on.

UKHeliBob:
Sorry to pour cold water on the idea but that is not going to work even with custom characters. In the first place the two rows characters are separated by a blank horizontal line. Secondly, there is a limit as to how many custom characters that you can create. You may be able to created enough to scroll a single digit up or down but certainly not if 2 different numbers need to be scrolled at the same time

Sure it can work.
The example shown only uses a single line of characters not multiple lines.
Also, in the example, there are only 8 actual digits scrolling.
To give the appearance of vertical scrolling digits, all you need is a single custom character for any scrolling digit position since all the needed custom characters do not have exist all at once.

So it could be done with the 8 custom characters available.
You have to do some clever remapping of the same custom character in the digit position but it definitely is possible.

For example, suppose you are scrolling the digit in position zero (the one furthest to the right).
And to make it easy lets assume that each digit is using the corresponding custom character code point.
i.e. digit zero uses 0, digit 1 uses 1 etc...
And suppose the current zero digit is a 1.
The custom character for code point 0 would be one that looks like a 1.
Now if you want to scroll it up to be a two, you now have to start re-programming the custom character at code point zero to look like the scrolling digits.
Even though there would be many different custom characters involved (total of eight) to do the animation, only a single custom character code point would be needed to scroll a digit position. You change the custom character each time you want to show the digit position moving up/down a pixel.

One way to do this would be to put all the custom character animation data into a table.
You create 10 entries each with 8 custom characters.
A double array table of custom characters - and each custom character is itself also an array.
(So technically, a tripple array )
Each entry would be the starting digit and then the 8 custom characters under that is the needed 8 characters to to do the animation.
entry zero is the 8 custom characters to scroll 0 to 1, entry 1 is the 8 custom characters to scroll 1 to 2 etc...

So if you wanted to transition from say 1 to 2, you would index into the table at two, then offset into the 8 custom character array one by one, reprogramming the custom character with a small delay between each one.
There is no need to do any printing or re-write a character to the LCD.
Simply re-programming the custom character will cause it to change on the display.

Now for the bad news. There are some "gotchyas" and some difficulties to do this with the IDE bundled LiquidCrystal library,particularly if you are wanting to do this on an AVR.

  1. The LiquidCrystal Library does not support AVR progmem custom character data.
    While it could be done with out using progmem on the AVR, The table for each direction would be 640 bytes.
    So 1280 bytes of RAM which might be exessive.
    This is also true of many other "LiquidCrystal" libraries.

  2. The createChar() call does not restore the LCD to DDRAM mode.
    I would call this a bug, and it exists in every "LiquidCrystal" library I've seen.
    The issue is that after calling createChar() the LCD is left in CGRAM mode which means that you must do something to put it back into DDRAM mode. That can be home(), clear(), or setCursor()

Now for some good news.
The hd44780 library supports progmem and does not have the createChar() issue.


After thinking about it some more, another alternate way would be to runtime create the needed custom character data when given the custom data for two digits and a scroll offset.
The code could pull what is needed from each digits character data to compose the custom character.
It could even handle up or down.
While slightly more complex, it would only require custom character data for the 10 digits and it would make it fairly easy to change the digit ont since you only need to change the individual digits vs an entire table.

This effect sounds very interesting, and in fact, I'm going to look at possibly implementing an example in hd44780 to demonstrate this.

--- bill

Here is a simple demo that I threw together.
It uses small digits rather than "normal" sized because I happened to already have these.
It is not pretty but demonstrates how it can be done.
Ideally the scrolling would use an index loop to be able to handle up to 8 digits rather than being hard coded for just 2 digits.

It was run using hd44780 as well as the bundled LiquidCrystal library.

--- bill

digitScrolling.ino (2.64 KB)

I was intrigued by this thread and wrote the code attached to handle the pushwheel type display of the number, as per OP. Works a bit differently from Bill's and needs more code, but it is more flexible (goes up and down), and uses full size digits. The transition character bitmaps for each digit are built on the fly, with the old digit scrolling off as the new one scrolls on.

The example sketch uses an LCD shield with analog switches, and the UP/DOWN switches are used to cause the number to change. Quite a bit of code is to handle the user switches.

An interesting little project that produces a cool text effect, even if limited to 8 digits. Could well use this in one of my future projects.

LCD_PushWheel.ino (8.58 KB)

Sorry to pour cold water on the idea but that is not going to work even with custom characters.

Gentlemen. Well done. Humble pie needed on my part.

What I find particularly interesting is that what I took to be a disadvantage, ie that redefining custom characters causes them to change on screen, turns out to be an advantage

marco,
Very nice.

You don't need to turn off the display and back on nor set the cursor position and re-draw the custom characters to get the new glyphs to show up.
The noDisplay() and display() creates lots of flicker and if using an i2c backpack to control the LCD it becomes unusable as the display is mostly off during the animation due to the slower i2c timing.

All you really need to do is update the custom character definitions.
You do have to get the custom characters in place on the display the very first time.
i.e.

void updateDisplay(uint8_t r, uint8_t c)
// do the necessary to display current number scrolling anchored
// on the LHS at LCD (r, c) coordinates.
{
static int writesdone = 0;
//  lcd.noDisplay();
  PRINTS("\nuD ")
  // for each digit position, create the lcd custom character and
  // display the custom character, left to right.
  for (uint8_t i = 0; i < MAX_DIGITS; i++)
  {
    PRINT(".", digits[MAX_DIGITS - i - 1].curr);
    lcd.createChar(i, digits[MAX_DIGITS - i - 1].charMap);
    if(!writesdone)
    {
        lcd.setCursor(c + i, r);
        lcd.write((uint8_t)i);
    }
  }

 // lcd.display();
}

But overall very nicely done.
I'm impressed.

--- bill

Thanks Bill.

The noDisplay() and display() creates lots of flicker and if using an i2c backpack to control the LCD it becomes unusable as the display is mostly off during the animation due to the slower i2c timing.

I was under the impression that these functions suspended updates to the display so that you can update the display buffer with the new 'screen' and then turn it all on at once. I can see from the function definition that this is not the case so they clearly are superflous in this case.

nor set the cursor position and re-draw the custom characters

lazy programming on my part...

marco_c:
Thanks Bill.
I was under the impression that these functions suspended updates to the display so that you can update the display buffer with the new 'screen' and then turn it all on at once. I can see from the function definition that this is not the case so they clearly are superflous in this case.
lazy programming on my part...

how about posting a video for posterity?

Here's a video link: MajicDesigns YouTube

Very nice! I know of another online community that may appreciate this. Thank you marco.