How to free RAM with PROGMEM?

I have a large program that runs low on memory.
So I wrote the following example sketch to learn about PROGMEM.
But PROGMEM is not freeing up RAM in this example.
Can PROGMEM work on any object, or does it only work on primitive types?

Output when USE_PROGMEM true:

Free SRAM = 2461

Output when USE_PROGMEM false:

Free SRAM = 2461

What am I doing wrong?

Example sketch:

/*
  Compare amount of free RAM used with and without PROGREM.
  If USE_PROGMEM true, all numbers and objects are const and PROGREM.
  If USE_PROGMEM false, all numbers and objects varaible.
  Print amount of free RAM at startup.

  Free SRAM is same regardless if PROGMEM is used or not.

  code is Modified Blink from Arduino IDE > Files > Examples > 01. Basics > Blink
  Turns LED on and off repeatedly.
*/
#include <inttypes.h>
#include <avr/pgmspace.h>

#define USE_PROGMEM false

// getFreeSram() code from http://web-engineering.info/node/30
// return amount of free RAM
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;

uint16_t getFreeSram() {
  uint8_t newVariable;
  // if heap is empty, use bss as start memory address
  if ((uint16_t)__brkval == 0)
    return (((uint16_t)&newVariable) - ((uint16_t)&__bss_end));
  // else use heap end as the start of the memory address
  else
    return (((uint16_t)&newVariable) - ((uint16_t)__brkval));
};

class Wait
{
    private:
        #if USE_PROGMEM
        const unsigned long milliseconds PROGMEM;
        #else
        unsigned long milliseconds;
        #endif
    public:
        Wait(unsigned long ms): milliseconds(ms) {}
        void ms()
        #if USE_PROGMEM
        const
        #endif
        {
            delay(milliseconds);
        }
};

#if USE_PROGMEM
const Wait wait1(10) PROGMEM;
const Wait wait2(20) PROGMEM;
const Wait wait3(30) PROGMEM;
const Wait wait4(40) PROGMEM;
const Wait wait5(50) PROGMEM;
const Wait wait6(60) PROGMEM;
const Wait wait7(70) PROGMEM;
const Wait wait8(80) PROGMEM;
const Wait wait9(90) PROGMEM;
#else
Wait wait1(10);
Wait wait2(20);
Wait wait3(30);
Wait wait4(40);
Wait wait5(50);
Wait wait6(60);
Wait wait7(70);
Wait wait8(80);
Wait wait9(90);
#endif

// Pin 13 has an LED connected on most Arduino boards.
// Pin 11 has the LED on Teensy 2.0
// Pin 13 has the LED on Teensy 3.0
int led = 11;

void setup()
{                
  pinMode(led, OUTPUT);
  Keyboard.begin();
  delay(1000);

  Keyboard.print(F("Free SRAM = "));
  Keyboard.println (getFreeSram ());
}

void loop()
{
  digitalWrite(led, HIGH);
  wait9.ms();
  digitalWrite(led, LOW);
  wait1.ms();
  wait2.ms();
  wait3.ms();
  wait4.ms();
  wait5.ms();
  wait6.ms();
  wait7.ms();
  wait8.ms();
  wait9.ms();

Can PROGMEM work on any object, or does it only work on primitive types?

Primitive types only. What you are trying to put in PROGMEM makes little sense.

        void ms()
        #if USE_PROGMEM
        const
        #endif
        {
            delay(milliseconds);
        }

What does wrapping the const in PROGMEM accomplish? What does const even mean for the function? Of course a function can't change at run time.

Thanks PaulS.

So I took PROGMEM off the non-primitive types.
The following example has PROGMEM only on unsigned long:
const PROGMEM unsigned long milliseconds;

Still, free SRAM is same regardless of PROGMEM being used or not:
USE_PROGMEM = 1, Free SRAM = 2425
USE_PROGMEM = 0, Free SRAM = 2425

/*
  Compare amount of free RAM used with and without PROGREM.
  If USE_PROGMEM true, all numbers and objects are const and PROGREM.
  If USE_PROGMEM false, all numbers and objects varaible.
  Print amount of free RAM at startup.

  Free SRAM is same regardless of PROGMEM being used or not:
    USE_PROGMEM = 1, Free SRAM = 2425
    USE_PROGMEM = 0, Free SRAM = 2425

  code is Modified Blink from Arduino IDE > Files > Examples > 01. Basics > Blink
  Turns LED on and off repeatedly.

  "const PROGMEM" did not upload
*/
#include <inttypes.h>
#include <avr/pgmspace.h>

#define USE_PROGMEM false

// getFreeSram() code from http://web-engineering.info/node/30
// return amount of free RAM
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;

uint16_t getFreeSram() {
  uint8_t newVariable;
  // if heap is empty, use bss as start memory address
  if ((uint16_t)__brkval == 0)
    return (((uint16_t)&newVariable) - ((uint16_t)&__bss_end));
  // else use heap end as the start of the memory address
  else
    return (((uint16_t)&newVariable) - ((uint16_t)__brkval));
};

class Wait
{
    private:
#if USE_PROGMEM
        const PROGMEM unsigned long milliseconds;
#else
        const unsigned long milliseconds;
#endif
    public:
        Wait(unsigned long ms): milliseconds(ms) {}
        void ms() const
        {
            delay(milliseconds);
        }
};

const Wait wait1(10);
const Wait wait2(20);
const Wait wait3(30);
const Wait wait4(40);
const Wait wait5(50);
const Wait wait6(60);
const Wait wait7(70);
const Wait wait8(80);
const Wait wait9(90);

const Wait waits[9] = { wait1, wait2, wait3, wait4, wait5, wait6, wait7, wait8, wait9};

// Pin 13 has an LED connected on most Arduino boards.
// Pin 11 has the LED on Teensy 2.0
// Pin 13 has the LED on Teensy 3.0
int led = 11;

void setup()
{                
  pinMode(led, OUTPUT);
  Keyboard.begin();
  delay(1000);
 
  Keyboard.print(F("USE_PROGMEM = "));
  Keyboard.print (USE_PROGMEM);

  Keyboard.print(F(", Free SRAM = "));
  Keyboard.println (getFreeSram ());
}

void loop()
{
  digitalWrite(led, HIGH);
  wait9.ms();
  digitalWrite(led, LOW);
  for (int i=0; i<9; i++)
  {
    waits[i].ms();
  }
}

“const” after a function declaration means that the function is not allowed to change any class members (except ones that are marked mutable).
http://www.cprogramming.com/tutorial/const_correctness.html > Const Functions

The preprocessor doesn't know what "false" or "true" is. An #if statement interprets a non-numeric value as zero, so #define USE_PROGMEM true is effectively the same as #define USE_PROGMEM false.

Thanks for catching that christop.

I changed the true/false to 1/0, but still get the same results:
USE_PROGMEM = 0, Free SRAM = 2425
USE_PROGMEM = 1, Free SRAM = 2425

The usual way to do that is Define with no value and then use #ifdef.

But sine PROGMEM only works on native types. It can't possibly put part of an instance of a class in PROGMEM.

You can't put non-static class variables into PROGMEM, it doesn't make any sense. Each time you make a new instance of the class it needs a different piece of RAM for that variable.

What Arduino do you have anyway?

Free SRAM = 2461

That sounds like a lot for a Uno.

Thanks Nick.
I am using Teensy 2.0

So PROGMEM is only for global primitive types.
Which means PROGMEM is fairly useless for Object Oriented C++.
Is that why C language is more popular with micro-processors?

wolfv:
So PROGMEM is only for global primitive types.
Which means PROGMEM is fairly useless for Object Oriented C++.
Is that why C language is more popular with micro-processors?

Were talking simple storage of data, not OO principles, you can put anything in PROGMEM.

But sine PROGMEM only works on native types. It can't possibly put part of an instance of a class in PROGMEM.

Paul is just assuming this. Part of an instance is silly, but an instance can be created in PROGMEM.

wolfv:
So PROGMEM is only for global primitive types.

No, you can put structures into PROGMEM.

Which means PROGMEM is fairly useless for Object Oriented C++.

I don't see the connection.

Is that why C language is more popular with micro-processors?

That is nothing to do with it.

Did you read the page I linked about PROGMEM?

pYro_65:
…you can put anything in PROGMEM.

…an instance can be created in PROGMEM.

That’s good news.

So I put PROGMEM on the objects, but PROGRMEM is actually using up more space!
Output, from compiling and running sketch twice:

Using PROGMEM:     Free SRAM = 2461
Not using PROGMEM: Free SRAM = 2425

Sketch:

/*
  Compare amount of free RAM used with and without PROGREM.
  If USE_PROGMEM true, all numbers and objects are const and PROGREM.
  If USE_PROGMEM false, all numbers and objects varaible.
  Print amount of free RAM at startup.

  Free SRAM is same regardless of PROGMEM being used or not:
    USE_PROGMEM = 1, Free SRAM = 2425
    USE_PROGMEM = 0, Free SRAM = 2425

  code is Modified Blink from Arduino IDE > Files > Examples > 01. Basics > Blink
  Turns LED on and off repeatedly.

  "const PROGMEM" did not upload
*/
#include <inttypes.h>
#include <avr/pgmspace.h>

#define USE_PROGMEM 0

// getFreeSram() code from http://web-engineering.info/node/30
// return amount of free RAM
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;

uint16_t getFreeSram() {
  uint8_t newVariable;
  // if heap is empty, use bss as start memory address
  if ((uint16_t)__brkval == 0)
    return (((uint16_t)&newVariable) - ((uint16_t)&__bss_end));
  // else use heap end as the start of the memory address
  else
    return (((uint16_t)&newVariable) - ((uint16_t)__brkval));
};

class Wait
{
    private:
        const unsigned long milliseconds;
    public:
        Wait(unsigned long ms): milliseconds(ms) {}
        void ms() const
        {
            delay(milliseconds);
        }
};

#if USE_PROGMEM
const PROGMEM Wait wait1(10);
const PROGMEM Wait wait2(20);
const PROGMEM Wait wait3(30);
const PROGMEM Wait wait4(40);
const PROGMEM Wait wait5(50);
const PROGMEM Wait wait6(60);
const PROGMEM Wait wait7(70);
const PROGMEM Wait wait8(80);
const PROGMEM Wait wait9(90);
#else
const Wait wait1(10);
const Wait wait2(20);
const Wait wait3(30);
const Wait wait4(40);
const Wait wait5(50);
const Wait wait6(60);
const Wait wait7(70);
const Wait wait8(80);
const Wait wait9(90);
#endif

const Wait waits[9] = { wait1, wait2, wait3, wait4, wait5, wait6, wait7, wait8, wait9};

// Pin 13 has an LED connected on most Arduino boards.
// Pin 11 has the LED on Teensy 2.0
// Pin 13 has the LED on Teensy 3.0
int led = 11;

void setup()
{                
  pinMode(led, OUTPUT);
  Keyboard.begin();
  delay(1000);
 
#if USE_PROGMEM
  Keyboard.print(F("Using PROGMEM:     Free SRAM = "));
#else
  Keyboard.print(F("Not using PROGMEM: Free SRAM = "));
#endif
  Keyboard.println (getFreeSram ());
}

void loop()
{
  digitalWrite(led, HIGH);
  wait9.ms();
  digitalWrite(led, LOW);
  for (int i=0; i<9; i++)
  {
    waits[i].ms();
  }
}

[quote author=Nick Gammon date=1443144184 link=msg=2410656]
No, you can put structures into PROGMEM.[/quote]
Does PROGMEM work on class objects?

[quote author=Nick Gammon date=1443144184 link=msg=2410656]
I don't see the connection.[/quote]
If I define a class but can't instantiate PROGMEM objects from it, then PROGMEM would be less useful in Object Oriented programming.

[quote author=Nick Gammon date=1443144184 link=msg=2410656]
Did you read the page I linked about PROGMEM?[/quote]
Thanks for the link Nick. Your examples are arrays of strings (which are not primitive types).
I have not found a PROGMEM example of class objects.

There is more to it than that, as the class var milliseconds is in PROGMEM, you must read it using pgm_read_xxx.

You create an array of Wait copies, so why even put the first ones in PROGMEM when you have an entire array of them still in RAM. (The key is to use pointers, not copies)

Your class must be a POD so you can initialize it using a brace-enclosed initializer. <<plenty of search terms.
This changes with C++11, but its not available by default yet.

wolfv:
Thanks for the link Nick. Your examples are arrays of strings (which are not primitive types).
I have not found a PROGMEM example of class objects.

Here for example: http://arduino.stackexchange.com/questions/13545/using-progmem-to-store-array-of-structs/13549#13549

A struct and a class are similar. However you cannot instantiate lots of class instances in PROGMEM, that simply doesn't make sense.

If I define a class but can't instantiate PROGMEM objects from it, then PROGMEM would be less useful in Object Oriented programming.

I don't see how you can expect to instantiate, at run time, lots of things which by definition in PROGMEM have to be constant and fixed.

The rest of your code can, however, use C++ methods.

Why not?

[quote author=Nick Gammon link=msg=2410699 date=1443149579]
I don't see how you can expect to instantiate, at run time, lots of things which by definition in PROGMEM have to be constant and fixed.[/quote]

If your data is read-only, the class can provide an interface for this data. We obviously aren't talking about run-time initialization of an object here!

I meant, run-time instantiate.

But that would be local variables, using new & delete, or creating an object which does not qualify as a trivial object. All types are instantiated at compile time, its a consequence of the static type system. At run time you can simply declare and define instantiated types.

Just in case there is a discrepancy here, you can use class member functions on an instance which is located in EEPROM or flash, the 'this' pointer simply is the PROGMEM address.

All types are instantiated at compile time, its a consequence of the static type system. At run time you can simply declare and define instantiated types.

No, that is not correct. A type is defined at compile time, but may be instantiated at run-time.

For example:

int * foo [100];
for (int i = 0; i < 100; i++)
   foo [i] = new (int);

That creates 100 instances of type int - at runtime.

No that is instantiating an object of a particular type.

Type instantiation is done by the compiler or linker. It is how it is able to do optimizations. A type definition describes what is instantiated...