I am just wondering if we have to free the memory in arduino like you have to in C?? Or is there a built in garbage collector?
If you are allocating memory using malloc(), operator new, etc, yes you do have to explicitly free it. The Arduino environment is not just like C, it is C++. I was confused on this point at first, because the programming language used in the Arduino IDE is described as a language called "Processing", though it turns out that Processing is really just C++ with a certain style of class library bolted on top.
On the other hand, I would be very careful with dynamic allocation of memory in such a constrained memory space. Instead of using things like linked lists, I would tend to reorganize my code to use arrays, and to very carefully budget out the less than 1K of RAM you have available!
So if I understand you correctly the memory allocation for variables is limited to less than 1k in size. And if this is the case would this cause the chip to not run if it is overloaded? Why I ask is because I am working on some code that has several char arrays with a moderate amount of characters in them and I can only get it to run with a set amount of arrays. When I add another array it just stops working ...
If you are willing to post your code, and/or a description of the problem you are solving, maybe we can get a better idea of how to optimize for memory usage. A lot of times there are ways to use a different algorithm, or simply to represent the same information using fewer bytes of memory.
Here is my code .. the following code is used to drive 3 shift registers that run a LED matrix of 64 LEDS (from sparkfun). The code here works fine but when I try to add another line/item (image) to the array gen_shps it stops working all together. The AVR chip just seems to not even run. I tried to define the array different ways and even just added the image strings directly in to the functions and it does the same thing which makes me think I am overloading the chip.
char *gen_shps[] = {
"oooggooo ooggggoo oggggggo ooggggoo oggggggo gggggggg oooyyooo oooyyooo", //x-mas tree
"oorrrroo orrrrrro oorrrroo ooorrooo oooggogo ogogggoo oogggooo oooggooo", //flower #1
"oorrrroo orooooro rogoogor roooooor rgoooogr rogoogor oroggoro oorrrroo", //smiley face
"oooooooo orroorro roorroor roorroor roooooor orooooro oorooroo ooorrooo", //heart
"ooogoooo ooogyooo ooogyyoo ooogyyyo ooogoooo gggggggg oggggggo ooggggoo", //boat
"ooorrooo oorooroo oorooroo ooorrooo oorooroo orooooro orrrrrro oorooroo", //girl
"oooooooo googggoo gogooogo ggoooyog ggooooog gogooogo googggoo oooooooo", //fish
"oooyyooo ooyooyoo oyyooyyo yooggooy yooggooy oyyooyyo ooyooyoo oooyyooo", //flower #2
"oorrrroo orrrrrro oorrrroo ooyrryoo oyooooyo oyooooyo ooyooyoo oooyyooo" //ring
};
int latchPin = 6; //RCLK (12)
int clockPin = 5; //SRCLK (11)
int dataPin = 7; //SER (14)
int cnt = 0;
int dSecs = 250;
int shp_speed = 5;
int type = 0;
int shift_reg[3][8] = {
{1,1,1,1,1,1,1,1}, // GND
{0,0,0,0,0,0,0,0}, // Red
{0,0,0,0,0,0,0,0} // Green
};
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(13, OUTPUT);
resetAll();
display();
}
void loop() {
for (int i=0;i<strlen(*gen_shps);i++) {
show(gen_shps[i], shp_speed);
}
}
void show(char item[], int timer) {
int size = strlen(item);
timer = timer*100;
while (timer > 1) {
if (size == 71) {
int char_cnt = 0;
int gnd_shift = 0;
int led_cnt = 0;
while (item[char_cnt] != '\0') {
shift_reg[0][gnd_shift] = 0;
switch (item[char_cnt]) {
case ' ':
display();
gnd_shift++;
led_cnt = 0;
break;
case 'g':
shift_reg[2][led_cnt] = 1;
led_cnt++;
break;
case 'r':
shift_reg[1][led_cnt] = 1;
led_cnt++;
break;
case 'y':
shift_reg[1][led_cnt] = 1;
shift_reg[2][led_cnt] = 1;
led_cnt++;
break;
default:
led_cnt++;
}
char_cnt++;
}
display();
}
timer--;
}
}
void display() {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin);
digitalWrite(latchPin, 1);
delayMicroseconds(dSecs);
resetAll();
}
void resetAll() {
for (int i=7; i>=0; i--) {
shift_reg[0][i] = 1;
}
for (int x=1; x<3; x++) {
for (int i=7; i>=0; i--) {
shift_reg[x][i] = 0;
}
}
}
void shiftOut(int myDataPin, int myClockPin) {
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
for (int x=0; x<3; x++) {
for (int i=7; i>=0; i--) {
digitalWrite(myClockPin, 0);
digitalWrite(myDataPin, shift_reg[x][i]);
digitalWrite(myClockPin, 1);
digitalWrite(myDataPin, 0);
}
}
digitalWrite(myClockPin, 0);
}
The data in this program could be made a lot smaller by using bit masks instead of strings. For one thing, the spaces are not necessary, because they appear every 8 characters. It would be possible to eliminate all of the spaces simply by keeping count of how many of the other characters have been loaded into the shift registers.
The only remaining characters are 'o', 'g', and 'r'. Since there are only 3 possible characters, you need only 2 bits to encode each, not an entire 8-bit character. Each group of 8 symbols could thus be represented in a 16-bit unsigned int.
This is the kind of situation where I have found it helpful to write a program that runs on my PC that reads in the human readable o/g/r symbols, converts them to the correct bit patterns, and generates the compressed data structure as a header file that can be included and used by the rendering program. Then you just download the compressed program + data into your Arduino.
You will need to learn about bitwise operations in C++ such as shift-left (<<) shift-right (>>), bitwise AND (&), bitwise OR (|), etc, in order to package and unpackage groups of bits from an integer.
I forgot to mention another possibility, which is to store the strings in program memory instead of RAM. Take a look at these functions...
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
I looked into using bitwise operators for this app, and I have to admit that I really do not fully understand them that well ... but everything I tried fell short of being able to represent the logical 4 states (off,red,green,yellow) I need. I looked at the examples in the forum that people posted but they are only good if you are dealing in 2 states(on/off). The bitwise operators seemed only to be good if you are looking at 0 and 1 .. but what if you need to get 2 and 3 also .. I am sure that it is my lack of understanding but could you provide an example and explain how it works????
One other thing ... you are right that the spaces are not needed and I did try it with them out of the array .. but it only saved a tiny bit and really does not make that much difference.
I also tried the program memory and it was a complete failure.....
Thank you
Hi xelwarto,
Here's some code that might help you to use an unsigned int to store 8 values of 4 states each:
unsigned int g_iFlag = 0;
unsigned int getState( unsigned int iFlag, unsigned int iIndex )
{
return 0x3 & ( iFlag >> ( iIndex * 2 ) );
}
void setState( unsigned int &iFlag, unsigned int iIndex, unsigned int iValue )
{
iFlag &= ~( 0x3 << ( iIndex * 2 ) );
iFlag |= ( iValue & 0x3 ) << ( iIndex * 2 );
}
void loop()
{
setState( g_iFlag, 3, 2 ); // Sets value 3 to state 2
unsigned int val = getState( g_iFlag, 3 ); // returns 2;
}
Hope this helps.
Lionel.