Skip to content

Commit 0945872

Browse files
author
Akshay Sharma
committed
Add Variables/Utilities PROGMEM and sizeof
1 parent 89fc89a commit 0945872

File tree

2 files changed

+254
-2
lines changed

2 files changed

+254
-2
lines changed
Lines changed: 174 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,174 @@
1-
//still to write
1+
:source-highlighter: pygments
2+
:pygments-style: arduino
3+
:ext-relative: adoc
4+
5+
6+
= PROGMEM
7+
8+
9+
// OVERVIEW SECTION STARTS
10+
[#overview]
11+
--
12+
13+
[float]
14+
=== Description
15+
Store data in flash (program) memory instead of SRAM. There's a description of the various http://www.arduino.cc/playground/Learning/Memory[types of memory] available on an Arduino board.
16+
17+
The `PROGMEM` keyword is a variable modifier, it should be used only with the datatypes defined in pgmspace.h. It tells the compiler "put this information into flash memory", instead of into SRAM, where it would normally go.
18+
19+
PROGMEM is part of the http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html[pgmspace.h] library. So you first need to include the library at the top your sketch, like this:
20+
21+
`#include <avr/pgmspace.h>`
22+
[%hardbreaks]
23+
24+
25+
[float]
26+
=== Syntax
27+
`dataType variableName[] PROGMEM = {dataInt0, dataInt1, dataInt3...};`
28+
29+
`program memory dataType` - any program memory variable type (see below)
30+
`variableName` - the name for your array of data
31+
32+
Note that because PROGMEM is a variable modifier, there is no hard and fast rule about where it should go, so the Arduino compiler accepts all of the definitions below, which are also synonymous. However experiments have indicated that, in various versions of Arduino (having to do with GCC version), PROGMEM may work in one location and not in another. The "string table" example below has been tested to work with Arduino 13. Earlier versions of the IDE may work better if PROGMEM is included after the variable name.
33+
34+
`dataType variableName[] PROGMEM = {}; // use this form` +
35+
`dataType PROGMEM variableName[] = {}; // not this one` +
36+
`PROGMEM dataType variableName[] = {}; // use this form`
37+
38+
While `PROGMEM` could be used on a single variable, it is really only worth the fuss if you have a larger block of data that needs to be stored, which is usually easiest in an array, (or another C data structure beyond our present discussion).
39+
40+
Using `PROGMEM` is also a two-step procedure. After getting the data into Flash memory, it requires special methods (functions), also defined in the http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html[pgmspace.h] library, to read the data from program memory back into SRAM, so we can do something useful with it.
41+
42+
As mentioned above, it is important to use the datatypes outlined in http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html[pgmspace.h]. Some cryptic bugs are generated by using ordinary datatypes for program memory calls. Below is a list of variable types to use. Floating point numbers in program memory do not appear to be supported.
43+
44+
`prog_char` - a signed char (1 byte) -127 to 128 +
45+
`prog_uchar` - an unsigned char (1 byte) 0 to 255 +
46+
`prog_int16_t` - a signed int (2 bytes) -32,767 to 32,768 +
47+
`prog_uint16_t` - an unsigned int (2 bytes) 0 to 65,535 +
48+
`prog_int32_t` - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647. +
49+
`prog_uint32_t` - an unsigned long (4 bytes) 0 to 4,294,967,295
50+
[%hardbreaks]
51+
--
52+
// OVERVIEW SECTION ENDS
53+
54+
55+
56+
57+
// HOW TO USE SECTION STARTS
58+
[#howtouse]
59+
--
60+
61+
[float]
62+
=== Example Code
63+
// Describe what the example code is all about and add relevant code ►►►►► THIS SECTION IS MANDATORY ◄◄◄◄◄
64+
The following code fragments illustrate how to read and write unsigned chars (bytes) and ints (2 bytes) to PROGMEM.
65+
66+
[source,arduino]
67+
----
68+
#include <avr/pgmspace.h>
69+
70+
71+
// save some unsigned ints
72+
PROGMEM prog_uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};
73+
74+
// save some chars
75+
prog_uchar signMessage[] PROGMEM = {"I AM PREDATOR, UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};
76+
77+
unsigned int displayInt;
78+
int k; // counter variable
79+
char myChar;
80+
81+
// read back a 2-byte int
82+
displayInt = pgm_read_word_near(charSet + k)
83+
84+
// read back a char
85+
myChar = pgm_read_byte_near(signMessage + k);
86+
87+
----
88+
*Arrays of strings*
89+
90+
It is often convenient when working with large amounts of text, such as a project with an LCD display, to setup an array of strings. Because strings themselves are arrays, this is in actually an example of a two-dimensional array.
91+
92+
These tend to be large structures so putting them into program memory is often desirable. The code below illustrates the idea.
93+
94+
[source,arduino]
95+
----
96+
/*
97+
PROGMEM string demo
98+
How to store a table of strings in program memory (flash),
99+
and retrieve them.
100+
101+
Information summarized from:
102+
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
103+
104+
Setting up a table (array) of strings in program memory is slightly complicated, but
105+
here is a good template to follow.
106+
107+
Setting up the strings is a two-step process. First define the strings.
108+
109+
*/
110+
111+
#include <avr/pgmspace.h>
112+
prog_char string_0[] PROGMEM = "String 0"; // "String 0" etc are strings to store - change to suit.
113+
prog_char string_1[] PROGMEM = "String 1";
114+
prog_char string_2[] PROGMEM = "String 2";
115+
prog_char string_3[] PROGMEM = "String 3";
116+
prog_char string_4[] PROGMEM = "String 4";
117+
prog_char string_5[] PROGMEM = "String 5";
118+
119+
120+
// Then set up a table to refer to your strings.
121+
122+
PROGMEM const char *string_table[] = // change "string_table" name to suit
123+
{
124+
string_0,
125+
string_1,
126+
string_2,
127+
string_3,
128+
string_4,
129+
string_5 };
130+
131+
char buffer[30]; // make sure this is large enough for the largest string it must hold
132+
133+
void setup()
134+
{
135+
Serial.begin(9600);
136+
}
137+
138+
139+
void loop()
140+
{
141+
/* Using the string table in program memory requires the use of special functions to retrieve the data.
142+
The strcpy_P function copies a string from program space to a string in RAM ("buffer").
143+
Make sure your receiving string in RAM is large enough to hold whatever
144+
you are retrieving from program space. */
145+
146+
147+
for (int i = 0; i < 6; i++)
148+
{
149+
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
150+
Serial.println( buffer );
151+
delay( 500 );
152+
}
153+
}
154+
----
155+
[%hardbreaks]
156+
157+
[float]
158+
=== Notes and Warnings
159+
[%hardbreaks]
160+
161+
[float]
162+
=== See also
163+
// Link relevant content by category, such as other Reference terms (please add the tag #LANGUAGE#),
164+
// definitions (please add the tag #DEFINITION#), and examples of Projects and Tutorials
165+
// (please add the tag #EXAMPLE#) ►►►►► THIS SECTION IS MANDATORY ◄◄◄◄◄
166+
167+
[role="example"]
168+
* #EXAMPLE# http://www.arduino.cc/playground/Learning/Memory[Types of memory available on an Arduino board]
169+
170+
[role="definition"]
171+
* #DEFINITION# link:array{ext-relative}[array] +
172+
* #DEFINITION# link:string{ext-relative}[string]
173+
--
174+
// HOW TO USE SECTION ENDS
Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,80 @@
1-
// still to write
1+
:source-highlighter: pygments
2+
:pygments-style: arduino
3+
:ext-relative: adoc
4+
5+
6+
= sizeof
7+
8+
9+
// OVERVIEW SECTION STARTS
10+
[#overview]
11+
--
12+
13+
[float]
14+
===
15+
The sizeof operator returns the number of bytes in a variable type, or the number of bytes occupied by an array.
16+
[%hardbreaks]
17+
18+
19+
[float]
20+
=== Syntax
21+
`sizeof(variable)`
22+
23+
24+
[float]
25+
=== Parameters
26+
`variable`: any variable type or array (e.g. int, float, byte)
27+
28+
[float]
29+
=== Returns
30+
Nothing
31+
32+
--
33+
// OVERVIEW SECTION ENDS
34+
35+
36+
37+
38+
// HOW TO USE SECTION STARTS
39+
[#howtouse]
40+
--
41+
42+
[float]
43+
=== Example Code
44+
// Describe what the example code is all about and add relevant code ►►►►► THIS SECTION IS MANDATORY ◄◄◄◄◄
45+
The `sizeof` operator is useful for dealing with arrays (such as strings) where it is convenient to be able to change the size of the array without breaking other parts of the program.
46+
47+
This program prints out a text string one character at a time. Try changing the text phrase.
48+
49+
[source,arduino]
50+
----
51+
char myStr[] = "this is a test";
52+
int i;
53+
54+
void setup(){
55+
Serial.begin(9600);
56+
}
57+
58+
void loop() {
59+
for (i = 0; i < sizeof(myStr) - 1; i++){
60+
Serial.print(i, DEC);
61+
Serial.print(" = ");
62+
Serial.write(myStr[i]);
63+
Serial.println();
64+
}
65+
delay(5000); // slow down the program
66+
}
67+
----
68+
[%hardbreaks]
69+
70+
[float]
71+
=== Notes and Warnings
72+
Note that `sizeof` returns the total number of bytes. So for larger variable types such as ints, the for loop would look something like this. Note also that a properly formatted string ends with the NULL symbol, which has ASCII value 0.
73+
74+
[source,arduino]
75+
----
76+
for (i = 0; i < (sizeof(myInts)/sizeof(int)) - 1; i++) {
77+
// do something with myInts[i]
78+
}
79+
----
80+
[%hardbreaks]

0 commit comments

Comments
 (0)