Cannot get PROGMEM to work

Hi Everyone.
I created 4 characters in a array and I can print each one on a Oled screen , using 28% memory.

Since I still need to add the rest of the characters and I will run out of memory.
I tried some samples of PROGMEM but the code still uses 28% memory and the characters now just print random pixels.

Some of the samples I tried.

/*const PROGMEM uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};
  const dataType variableName[] PROGMEM = {}; // use this form
  const PROGMEM dataType variableName[] = {}; // or this one
  const dataType PROGMEM variableName[] = {}; // not this one
*/

const PROGMEM byte data[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 
 0xF8, //48 bytes
                             0xFF, 0x1F, 0x1C, 0x00, 0x38, 0x0E, 0x00, 0x70, 0x07, 0x00,
                             0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0,
                             0x0E, 0x00, 0x70, 0x1C, 0x00, 0x38, 0xF8, 0xFF, 0x1F, 0xF0,
                             0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

My full code


//##################
//   DIGISPARK
//##################
/*
   print 0 or 1 or 2 or 3 on Oled
*/

#include <Wire.h>

#define OLED_I2c_ADDRESS       0x3d//   0x3C
// registers Addresses
#define COMMAND_REG    0x80  // B1000 0000
#define DATA_REG       0x40  // B0100 0000
// commands
#define ON_CMD                0xAF
#define NORMAL_DISPLAY_CMD    0xA6//  INVERT B/W = 0xA7
#define PAGE_ADDRESSING_MODE  0x03 // 

int dataPos = 144;//start of progmem first page

int  xPos = 0;
int  yPos = 0;

//=====BIG FONTS==24H X 16W==========
//===== 0,1,2,3 ====

/*const PROGMEM uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};
  const dataType variableName[] PROGMEM = {}; // use this form
  const PROGMEM dataType variableName[] = {}; // or this one
  const dataType PROGMEM variableName[] = {}; // not this one
*/

const PROGMEM byte data[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0xF8, //48 bytes
                             0xFF, 0x1F, 0x1C, 0x00, 0x38, 0x0E, 0x00, 0x70, 0x07, 0x00,
                             0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0,
                             0x0E, 0x00, 0x70, 0x1C, 0x00, 0x38, 0xF8, 0xFF, 0x1F, 0xF0,
                             0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                             //===== 1 = 48 ===
                             0x00, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x38, 0x00, 0xE0, 0x3C,
                             0x00, 0xE0, 0x1E, 0x00, 0xE0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                             0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00,
                             0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                             //==== 2 = 96
                             0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x3C, 0x00, 0xFC, 0x3E,
                             0x00, 0xFE, 0x0E, 0x00, 0xFF, 0x07, 0x00, 0xEF, 0x07, 0x80,
                             0xE7, 0x07, 0xC0, 0xE3, 0x07, 0xE0, 0xE1, 0x07, 0xF0, 0xE0,
                             0x1E, 0x78, 0xE0, 0xFE, 0x3F, 0xE0, 0xFC, 0x1F, 0xE0, 0xF0,
                             0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                             //==== 3 = 144
                             0x00, 0x00, 0x00, 0x38, 0x00, 0x1C, 0x3C, 0x00, 0x3C, 0x1E,
                             0x00, 0x78, 0x07, 0x00, 0xE0, 0x03, 0x00, 0xC0, 0x03, 0x38,
                             0xC0, 0x03, 0x38, 0xC0, 0x03, 0x38, 0xC0, 0x07, 0x7E, 0xE0,
                             0x0E, 0xFE, 0x60, 0x1E, 0xE7, 0x79, 0xFC, 0xC3, 0x3F, 0xF8,
                             0x81, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                            };
void setup()
{
  oled_begin();
  setCursor(50, yPos); //x,y
}

void loop()
{
  //======== THIS WORKS FONT CREATOR =============

  //char 0 dataPos 0

  //char 1 dataPos 48

  //char 2 dataPos 96

  //char 3 dataPos 144

  for (int i = 0; i < 16; i++)
  {
    writeData(data[dataPos]);
    dataPos = dataPos + 3;//Select every 3 rd byte
  }
  yPos = yPos + 1;
  dataPos = 144;// char start pos in array
  dataPos = dataPos + yPos;//jump to next array adress from 0
  setCursor(50, yPos ); //x,y

  if (yPos > 2)//page number
  {
    while (1)
    {}
  }

}

//===================================

void oled_begin()
{
  Wire.begin(); // join i2c bus (address optional for master)
  turnON();
  NormalDisplayMode();
  //setPageMode();
  writeCommand(0x8d); //Charge Pump
  writeCommand(0x14);
  clearFullDisplay();
}


void writeCommand(byte command) {
  Wire.beginTransmission(OLED_I2c_ADDRESS); // begin transmitting  (OLED_I2c_ADDRESS=0x3C)
  Wire.write(COMMAND_REG);                  // Command Reg Address (COMMAND_REG     =0x80 )
  Wire.write(command);                      // Command to be excuted
  Wire.endTransmission();                   // stop transmitting
}

void writeData(byte data) {
  Wire.beginTransmission(OLED_I2c_ADDRESS); // begin transmitting   (OLED_I2c_ADDRESS=0x3C)
  Wire.write(DATA_REG);                     //Data Reg Address      (DATA_REG        =0x40)
  Wire.write(data);                         //Write data
  Wire.endTransmission();                   // stop transmitting
}

void turnON() {
  writeCommand(ON_CMD);
}
void NormalDisplayMode()
{
  writeCommand(NORMAL_DISPLAY_CMD);
}
void setPageMode()
{
  byte addressingMode = PAGE_ADDRESSING_MODE;
  writeCommand(0x20);        //set addressing mode
  writeCommand(PAGE_ADDRESSING_MODE);   //set page addressing mode
}

void clearFullDisplay()
{
  for (byte page = 0; page < 8; page++)
  {
    setCursor(0, page);
    for (byte column = 0; column < 130; column++)
    { //clear all columns..was128 pixels left far right
      writeData(0x00);
    }
  }

}

void setCursor(byte Y, byte X)
{
  writeCommand(0x00 + (Y & 0x0F));        //set column lower address
  writeCommand(0x10 + ((Y >> 4) & 0x0F)); //set column higher address
  writeCommand(0xB0 + X);                 //set page address
}

Reading from PROGMEM requires special instructions.
Check the reference page.

I did see that page but still missing something ,This is from the reference page that I tried.

You need to use special instructions to read data from PROGMEM

See Why use PROGMEM in Arduino? - LogiqBit.

Thanks for the pointers.
Program storage went down from 28% to 21%
I manage to read from PROGMEM with this changed line.

 {data = (pgm_read_byte(&myArray[dataPos]));
    writeData(data);
    dataPos = dataPos + 3;//Select every 3 rd byte
  }

Byte 0,3,6,9 ....... print the top part of the character
Byte 1,4,7,10 ..... print the middel part
Byte 2,5,8,11..... print the bottom

image

Using PROGMEM really should not affect program storage that much, the main effect is to save dynamic memory (ram), and often program memory usage will increase by a few bytes because of the extra instructions needed to fetch the data from PROGMEM. If your program memory use dropped that much you must have changed something else in the code.

Correct .. I have no idea what I am doing.

When I save the Array like this , prog memory is 26% used.

const PROGMEM byte myArray[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0xF8, //48 bytes
                                0xFF, 0x1F, 0x1C, 0x00, 0x38, 0x0E, 0x00, 0x70, 0x07, 0x00,
                                0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0,
                                0x0E, 0x00, 0x70, 0x1C, 0x00, 0x38, 0xF8, 0xFF, 0x1F, 0xF0,
                                0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

When I use this , also 26% prog memory used.

byte myArray[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0xF8, //48 bytes
               0xFF, 0x1F, 0x1C, 0x00, 0x38, 0x0E, 0x00, 0x70, 0x07, 0x00,
               0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0,
               0x0E, 0x00, 0x70, 0x1C, 0x00, 0x38, 0xF8, 0xFF, 0x1F, 0xF0,
               0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

The values for an initialised array have to be stored in flash memory, even if the array exists as const, but resides in RAM.
PROGMEM simply ensures it remains in flash, and doesn't get copied to RAM

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