lcd.createChar PROGMEM

Hi I have 4 byte arrays and am using as custom characters for lcd. I`m storing them in global variables because after trying different combinations of storing in setup then in loop or in other functions found that in global its taking less memory. at least IDE is showing me that.

I tried storing in flash via progmem then reading in in creatchar which gives me corrupted characters.

I gues because I was using pgm_byte_read and giving address of byte instead of short or may be didn't figure out how return of pgm_byte_read will affect lcd.createChar.

const byte thin[8] = {
  B10000,
  B01000,
  B00100,
  B00010,
  B00001,
  B00010,
  B00100,
  B01000,
};

void setup(){
....
lcd.createChar(0, thin);
}

this way it is working as it should.

I tried way with progmem which gave me corrupted characters.

Which LiquidCrystal Library are you using?

The default one only implements

// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) {
  location &= 0x7; // we only have 8 locations 0-7
  command(LCD_SETCGRAMADDR | (location << 3));
  for (int i=0; i<8; i++) {
    write(charmap[i]);
  }
}

so expects data in SRAM => you would need to read into a memory buffer the flash memory before calling the function

That being said, It’s not rocket science to add a function to your library to do so if it’s not supported, something like

void LiquidCrystal::createChar(uint8_t location, const char *charmap) {
  location &= 0x7; // we only have 8 locations 0-7
  command(LCD_SETCGRAMADDR | (location << 3));
  for (int i=0; i<8; i++) {
    write(pgm_read_byte_near(charmap++)); // reading from progmem
  }
}

might just be enough to get it to work (untested).
Of course need to add the new method signature to the .h as well

thanks! will test tomorrow.

Yes I`m using default one.

Didnt work.

If i am declaring custom chars as globals and putting in flash via progmem and reading them via pgm_read_byte_near into other variable in the some function called from setup() and in same setup() calling createChar() to create chars in lcd shouldnt it free ram after it will exit the function?

All i need is save as much ram as possible for other heavy functions.

surepic:
Didnt work.

Go on, give us a clue... post the code please.

Yours,
TonyWilk

surepic:
Didnt work.

I’m pretty sure it Works for me, but i’ll Do as you do, keep the code to myself...

Sorry was writing from my phone will post the code when will reach to my laptop.

surepic:
Hi I have 4 byte arrays and am using as custom characters for lcd. I`m storing them in global variables because after trying different combinations of storing in setup then in loop or in other functions found that in global its taking less memory. at least IDE is showing me that.

I tried storing in flash via progmem then reading in in creatchar which gives me corrupted characters.

I gues because I was using pgm_byte_read and giving address of byte instead of short or may be didn’t figure out how return of pgm_byte_read will affect lcd.createChar.

const byte thin[8] = {

B10000,
 B01000,
 B00100,
 B00010,
 B00001,
 B00010,
 B00100,
 B01000,
};

void setup(){

lcd.createChar(0, thin);
}




this way it is working as it should.

I tried way with progmem which gave me corrupted characters.

ADD these to your [b]LiquidCrystal [/b]library:

//////////////////// ADD this to LiquidCrystal.cpp ////////////////

// custom bitmaps in PROGMEM
void LiquidCrystal::createChar_P (uint8_t addr, const char *bitmap)
{
    createChar_P (addr, (const uint8_t *)(bitmap));
}

void LiquidCrystal::createChar_P (uint8_t addr, const uint8_t *bitmap)
{
    uint8_t n;

    command (SETCGRAMADDR | ((addr % 8) * 8));

    for (n = 0; n < 8; n++) {
        write (pgm_read_byte (bitmap + n));
    }

    home();  // make sure cursor isn't fubar
}

////////////////////////// ADD this to LiquidCrystal.h ///////////////////

    void createChar_P (uint8_t, const char *);
    void createChar_P (uint8_t, const uint8_t *);

…and now you can put your custom LCD characters into PROGMEM.

@krupski just copied your code directly to cpp and h. SETCGRAMADDR has to be LCD_SETCGRAMADDR .
and everything works great.

before
Global variables use 516 bytes (25%) of dynamic memory, leaving 1532 bytes for local variables. Maximum is 2048 bytes.

after
Global variables use 484 bytes (23%) of dynamic memory, leaving 1564 bytes for local variables. Maximum is 2048 bytes.

32byte saved from ram 4byte arrays 8elements each.

Ok, this is an old post. For clarity sake and maybe to help others who will have the same problem, I will just reply to this post and ask the remaining question.

I have modified LiquidCrystal_I2C.h and .cpp by adding the lines shown by krupski in post #7 above and also made the required changes to the lines because the krupski code assumed LiquidCrystal instead of LiquidCrystal_I2C (class Name in the method declarations and the Change to command as indicated by surepic).

surepic indicated in post #8 above that he then got it working and reduced the memory used for variables in the sketch.

My questions are:

  1. How exactly should the array of data describing the desired character be defined in the sketch?
  2. How exactly should the new function be called in the sketch?
  3. Is it possible to use/modify this code in such a way that the lcd characters are in a multidimensional Array? ( uint8_t lcdchar[6][8]) so that createChar can be called from within a for loop instead of multiple times?

Thanks!

@JaBa

first create custom chars in globals and place in progmem. These are my arrows.
const byte thin[8] PROGMEM = {
B10000,
B01000,
B00100,
B00010,
B00001,
B00010,
B00100,
B01000,
};
const byte thick[8] PROGMEM = {
B10000,
B11000,
B11100,
B11110,
B11111,
B11110,
B11100,
B11000,
};

initialising lcd via lcd.begin and
then in lcd.createchar in Setup cos my animation is in setup portion and I had to save ram in main loop.

lcd.createChar_P(0, thin);
lcd.createChar_P(1, thick);

I`m calling the function in setup() directly.

Animation();

in animation function:
I`m writing the chars which I named 0 and 1 respectively (lcd.createchar_p(0,thin)) directly to lcd via lcd.write.

example:
lcd.write(0) or lcd.write(1)

Mine is in for loop but cant picture char in multi array.

Thanks surepic, that helped. No idea why I wasn’t able to figure it out.

It now compiles correctly and Shows the reduction in usage of variable Memory.

What I was talking about with multi-dimensional Arrays and a for Loop is more like:

const byte lcdchars[2][8] PROGMEM = {
{B10000, B01000, B00100, B00010, B00001, B00010, B00100, B01000},
{B10000, B11000, B11100, B11110, B11111, B11110, B11100, B11000}};

for(i = 0; i<2;i++)
lcd.createChar_P(i, lcdchars*);*
That compiles but I haven’t actually tested it on a LCD Display yet (on the road again).
Thanks, Karma awarded!