PSTR and it's use.

Hello all again.

What is PSTR and how should it be used? I understand it's something about just using flash instead of flash and ram?

Many thanks ppl.

For example:

Serial.print("This is a test - Hello world!!");

uses SRAM for the string, so few such prints and your SRAM is full.

You may use:

Serial.print(F("This is a test - Hello world!!"));

and it uses FLASH for storing the string, thus you save the SRAM. p.

1 Like

http://www.arduino.cc/playground/Learning/Memory http://arduino.cc/en/Reference/PROGMEM http://arduino.cc/playground/Main/Printf

I get this error when i try to use Serial.println(F(SoftwareVersion)); SoftareVersion = const char SoftwareVersion[] = "v0_1_0";

warning: only initialized variables can be placed into program memory area initializer fails to determine size of'__c'

Any ideas?

F is a macro, not a function. It expects something that looks to the compiler as a string literal, not a string constant.

Thank you :).

I have used #define SoftwareVersion "v0.1.0\r" then used the Serial.println(F(SoftwareVersion));. Saves some space.

Does the PSTR/F macro work with the SoftwareSerial library? My sketch works with PSTR with Serial.print(); but don't with the SoftwareSerial.print();.

ie. (ide 1.0.1): Serial.println(F("Unable to sync with the RTC")); lcd.print(F("Pa/30min")); myFile.print(F(","));

Here is a sketch that shows a user i/o command processor (allows variables to be changed while the sketch is running) and use of PROGMEM to store menus and help messages and print those out using 1 char of SRAM rather than a full-width buffer.

tested, working a while ago:

#include <avr/io.h>
#include <avr/pgmspace.h>

unsigned long  mark = 0UL; // time and duration storage
unsigned long  now = mark;
unsigned long  last = now;

const char PROGMEM report[][20] = { 
  "\nedited: vertical ", " ... timescaler " };

const char PROGMEM tapLabel[3][20] = 
{
  "vertical value: ", " | tap + side: ", " | tap - side " };

const char PROGMEM usageMsg[][80] = { // all this text stored in flash
  "          Piezo touch sensor tuner.",
  "Adjust vertical; enter W to subtract or X to add, and a number 0-255",
  "Adjust timescaler; enter A to subtract or D to add, and 0-16535",
  "to add 250 to vertical enter W250 in Serial Monitor and press enter",
  "seperate multiple commands with spaces; ex: W25 D240",
  "    ** this message stored in flash ram **",
  "    ** and printed with a 1 byte buffer ** :-P"
};

PGM_P Msg; // pointer into flash memory

#define  MAXVERT    255
#define  MAXSCALE   16535
#define  HELPLINES  7

unsigned long  vertical = 0UL; // just a varible with meaningful name
unsigned long  timescaler = 0UL; // ditto, not used any more except to change
unsigned long  temp;

byte B, command;


void  printMsg( PGM_P FM )
{
  do 
  {
    B = pgm_read_byte( FM++ );    
    if ( B )  Serial.print( B );
  }
  while ( B );
}

void printHelp(void)
{
  for ( byte i = 0; i < HELPLINES; i++ )
  {
    printMsg( usageMsg[ i ]);
    Serial.println();
  }
  Serial.println();
}

void setup(void)
{
  Serial.begin(9600);
  printHelp();
} 

void loop(void)
{
  // there used to be code to read touch sensors here, put something else in
  
  // below reads serial input and reacts to single character commands
  // with multidigit numbers following, like R500
  // this might do, you might want to do more

  // it's a real -simple- user i/o to tune variables used in now some other code
  // a command line might look like D133, adding 133 usec to the timescaler
  
  // all that happens in this sketch is two variables get changed
  // those are vertical and timescaler just to provide examples with names
  // timescaler usecs had to run out between digital HIGH read adds 1 to a counter
  // that counter makes a digital pin into an ADC with variable possible precision
  // each pin had a capacitor 

  if ( Serial.available())
  {
    B = Serial.read();
    Serial.print( B );

    if ( !command ) // only TRUE when command == 0
    {
      temp = 0UL;

      if (( B & 0xDF ) == 'X' )  
      {
        command = 1;
        return;  // shortcut back to loop() to wait for the next serial read
      }
      else if (( B & 0xDF ) == 'W' )
      {
        command = 2;
        return;  // shortcut back to loop()
      }
      else if (( B & 0xDF ) == 'A' )
      {
        command = 3;
        return;  // shortcut back to loop()
      }
      else if (( B & 0xDF ) == 'D' )
      {
        command = 4;
        return;  // shortcut back to loop()
      }
    }
    else // looking for digits only, will limit and fit into an unsigned long
    {
      if (( B >= '0' ) && ( B <= '9')) // first turn digits into a value
      {
        temp *= 10UL;
        temp += (unsigned long) ( B - '0' ); // so all numbers build in temp
      }
      else  // as soon as it finds a non-digit, it assumes that to be a separator
      // it's not bulletproof but doesn't allow values out of range
      {
//        Serial.println();            // debug code
//        Serial.print( "command " );
//        Serial.print( command, DEC );
//        Serial.print( "  temp " );
//        Serial.println( temp, DEC );
//        Serial.println();

        switch ( command ) // next apply that number to the program variables
        {
        case  1:
          {
            if ( vertical < temp )
            {
              vertical = 0UL;
            }
            else
            {
              vertical -= temp;
            }
            command = 0;
            break;
          }

        case  2:
          {
            if ( vertical + temp > MAXVERT )
            {
              vertical = MAXVERT;
            }
            else
            {
              vertical += temp;
            }
            command = 0;
            break;
          }

        case  3:
          {
            if ( timescaler < temp )
            {
              timescaler = 0UL;
            }
            else
            {
              timescaler -= temp;
            }
            command = 0;
            break;
          }

        case  4:
          {
            if ( timescaler + temp > MAXSCALE )
            {
              timescaler = MAXSCALE;
            }
            else
            {
              timescaler += temp;
            }
            command = 0;
            break;
          }

        default:
          {
            command = 0;
            temp = 0UL;
            printHelp(); // carriage return will trigger this
            return; // includes no command == 0 does not print status
          }
        }
        // breaks above go here
        printMsg( report[ 0 ]); // "\nedit: vertical "
        Serial.print( vertical );
        printMsg( report[ 1 ]); // " ... timescaler "
        Serial.println( timescaler );
      }
    }
  } 
}

Thank you, i have this all sorted now and freed up some SRAM by using this function.