I'm having a bit of an issue with my int* array, and I don't really know where to begin, so here goes...
I'm trying to build a "memory game" that gets increasingly harder, where some LEDs should blink in sequence and the user must remember the sequence.
For the first 3 "levels", everything seems to be just fine, but by the 4th (and following) stage, then my data in the sequence array seems to be messed up somehow. I cannot see any pattern in how the data is messed up.
I'm creating my sequence as a part of setup() and does not write to it since.
Am I missing something fundamental here?
I've dumped some output from the Serial interface (http://pastebin.com/5axEvZTf) for easier understanding of what's going on.
Unfortunately I haven't been able to narrow down where my error is, so I've attached my entire code below.
I'm hoping for some advice on what causes this strange behavior
/*
* TODO: Something smarter for blink and on/off methods
* so we can have a veriable amount of colors to
* adjust the difficulty
*/
const int r_out = 8;
const int g_out = 9;
const int b_out = 10;
const int wait = 200;
int stage;
int* sequence;
void setup() {
// Set up serial and wait for it to be ready
Serial.begin(9600);
while(!Serial){
;
}
// Building a sequence of X elements
sequence = buildSequence(10);
delay(5000);
stage = 1;
pinMode(r_out, OUTPUT);
pinMode(g_out, OUTPUT);
pinMode(b_out, OUTPUT);
//test();
}
void loop() {
Serial.print("Starting stage ");
Serial.println(stage);
for(int i = 0;i<3;i++){
allOff();
delay(wait);
allOn();
delay(wait);
allOff();
delay(wait);
}
Serial.println("Starting sequence");
for(int i = 0;i<stage;i++){
Serial.print("Blinking on port ");
Serial.println(sequence[i]);
switch(sequence[i]){
case r_out:
rBlink();
break;
case g_out:
gBlink();
break;
case b_out:
bBlink();
break;
}
}
stage++;
Serial.println("Done with stage. Starting next");
Serial.println();
delay(10000);
}
// Test to see if all LEDs work as they should
void test(){
for(int i = 0;i<5;i++){
rBlink();
gBlink();
bBlink();
}
for(int i = 0;i<5;i++){
allOn();
delay(500);
allOff();
delay(500);
}
}
void rBlink(){
rOn();
delay(wait);
rOff();
delay(wait);
}
void gBlink(){
gOn();
delay(wait);
gOff();
delay(wait);
}
void bBlink(){
bOn();
delay(wait);
bOff();
delay(wait);
}
void allBlink(){
allOn();
delay(wait);
allOff();
}
void rOn(){
digitalWrite(r_out, HIGH);
}
void gOn(){
digitalWrite(g_out, HIGH);
}
void bOn(){
digitalWrite(b_out, HIGH);
}
void rOff(){
digitalWrite(r_out, LOW);
}
void gOff(){
digitalWrite(g_out, LOW);
}
void bOff(){
digitalWrite(b_out, LOW);
}
void allOff(){
rOff();
gOff();
bOff();
}
void allOn(){
rOn();
gOn();
bOn();
}
int* buildSequence(int len){
int pins[] = {r_out, g_out, b_out};
int sequence[len];
for(int i = 0;i<len;i++){
int num = random(0,3);
sequence[i] = pins[num];
Serial.print("Adding to sequence:");
Serial.print(pins[num]);
Serial.println();
}
Serial.println();
return sequence;
}
Hi,
I have had a brief look at your sketch.
I wonder if you are aware that an array that is declared as 10 items, has its contents addressed as item 0, item 1 up to item 9.
The use of two variables called sequence is a little confusing and possibly dangerous as you might
Your problem is that you create a sequence array in buildSequence; that array will be allocated on the stack. When you leave the function, the array basically no longer exists and can be overwritten by anything.
One solution might be using dynamic memory like below.
int* buildSequence(int len) {
int pins[] = {r_out, g_out, b_out};
// if already allocated, free first
if (sequence != NULL)
{
free(sequence);
}
// allcoate memory
sequence = (int*)malloc(len * sizeof(int));
// check result; bail out if allocation failed
if (sequence == NULL)
{
// error; memory could not be allocated
return NULL;
}
// whatever you were doing here
for (int i = 0; i < len; i++) {
int num = random(0, 3);
sequence[i] = pins[num];
Serial.print("Adding to sequence:");
Serial.print(pins[num]);
Serial.println();
}
Serial.println();
return sequence;
}
Notes:
whenever you call this version of buildSequence, you need to check the returned value for null
you can also make use of realloc (no need to free first) and calloc instead of malloc (calloc will initialize the allocated memory)
not tested
//Edit
You need to initialize your sequence pointer in the beginning of your code to NULL
Thanks for your replies... I got it to work when I moved sequence to the global scope!
I think my confusion is from other programming languages where multiple variables can have same name, but live in diffrent scopes (e.g. JavaScript)....
EsbenBoye:
Thanks for your replies... I got it to work when I moved sequence to the global scope!
I think my confusion is from other programming languages where multiple variables can have same name, but live in diffrent scopes (e.g. JavaScript)....
Thank a lot!
Same as C++... multiple variables can have the same name in different scopes. You bumped into the issue of using one in GLOBAL scope with another of the same name local to a function... and that comes with its complications, to say the least!