Go Down

Topic: Debugging errors.. Returning an array from a Func (Read 879 times) previous topic - next topic

entplex

I'm working on a sketch that takes input from a sonar sensor on an analog pin and then writes it to serial output.  The data is stored in an array, so that a running average and the smallest number in the array can be calculated.  I'm wanting to keep this as function based as possible as in the future it will make life a lot easier.  This is the first function based sketch I'm writing, so forgive me if I have done anything in an illogical manner.  The sensor will ultimately scan back and forth.  This sketch is just to test the functionality of what I'm trying to do.  It is giving a...
"In function 'int AppendDistance(int*, int)':
error: expected primary-expression before ']' token In function 'void loop()':"
debug error on line 60.  Any suggestions and help is appreciated.

Code: [Select]

int distances[] = {0,0,0,0,0,0,0,0,0,0};
int ez1Pin = 0;

void setup() {
     pinMode(ez1Pin,INPUT);
     beginSerial(9600);
}
// find the position of the smallest number in an array
int MinVal (int array[], int arrayVals){
     int result;
     int i = 0;
     int tempval=array[1];
     //maybe a min woulde be better used here....
     for (i = 0;i<arrayVals;i++){
           if (tempval<array[i]){
                 result=i;
           }
     }
     return result;
}


//find the average of an array, this is only needed if there are multiple values being written to the
//scaning array
int Avg (int array[], int arrayVals){
     int result;
     int i = 0;
     int sum;
     for (i=0;i<arrayVals;i++){
           sum = array[i]+sum;
     }
     result = sum / arrayVals;
     return result;
}

//reads the current distance
int GetDistance(){
     int result = analogRead(ez1Pin);
     if (result > 0){
           result = result / 2;
     }
     return result;
}

//takes an array and appends the current distance at the end of it, moving all values and deleting the first
int AppendDistance (int dd[], int arrayVals){
     int i = 0;

     for(i=0;i<arrayVals;i++){                  //should this be i<arrayVals or i<=arrayVals
           if (i=1){
                 dd[1]=dd[2];
           }
           else if (i=arrayVals){
                 dd[i] = GetDistance();
           }
           else{
           dd[i]=dd[i+1];
           }
     }
       return dd[];
}
     
void loop() {
     distances[] = AppendDistance(distances, 10);
     AverageDistance=Avg(distances,10);
     MinimumDistance=MinVal(distances,10);
     Serial.println(distances);
     Serial.print("The Mean is :");
     Serial.print(AverageDistance);
     Serial.print("The Min is :");
     Serial.print(distances[MinimumDistance]);
     Serial.print(" , In position :");
     Serial.print(MinimumDistance);
     delay(300);      
}

entplex

I have revised this and got it working in a bit different way, figured I would share it in case anyone comes across this in the future.

Code: [Select]
int distances[] = {0,0,0,0,0,0,0,0,0,0};
int ez1Pin = 2;
int AverageDistance = 0;
int MinimumDistance = 0;
int SonarSamps = 9;
int i=0;


void setup() {
 pinMode(ez1Pin,INPUT);
 beginSerial(28800);
}

// find the position of the smallest number in an array
int MinVal (int array[], int arrayVals){
 int result=0;
 int i = 0;
 int tempval = array[0];
 //maybe a min woulde be better used here....
 for (i = 0;i<arrayVals;i++){
   if(tempval>array[i]){
     tempval=array[i];
     result=i;
   }
 }
 return result;
}


//find the average of an array, this is only needed if there are multiple values being written to the
//scaning array
int Avg (int array[], int arrayVals){
 int result;
 int i = 0;
 int sum;
 for (i=0;i<=arrayVals;i++){
   sum = array[i]+sum;
 }
 result = sum / arrayVals;
 return result;
}

//reads the current distance
int GetDistance(){
 int result = analogRead(ez1Pin);
 if (result > 0){
   result = result / 2;
 }
 return result;
}

//takes an array and appends the current distance at the end of it, moving all values and deleting the first

void loop() {
 
//Takes a sample from the Sonar  and appends it to the distances array
 i=0;
 for(i=0;i<=SonarSamps;i++){
   if (i==0){
     distances[0]=distances[1];
   }
   else if(i==SonarSamps){
     distances[i] = GetDistance();
   }
   else{
     distances[i]=distances[i+1];
   }
 }
//end sampling and appending

 AverageDistance=Avg(distances, SonarSamps+1);
 MinimumDistance=MinVal(distances,SonarSamps);
 Serial.print("[");
 for (i=0;i<=SonarSamps;i++){  
   Serial.print(distances[i]);
   Serial.print(", ");
 }
 Serial.print("]");
 Serial.println();
 Serial.print("The Mean is :");
 Serial.print(AverageDistance);
 Serial.print("  The Min is :");
 Serial.print(distances[MinimumDistance]);
 Serial.print(" , In position :");
 Serial.print(MinimumDistance);
 Serial.println();
 delay(1000);      
}


MysteriousAges

Your array syntax was not correct, that's why you the first sketch you posted didn't compile. Namely, the compiler didn't like

return dd[];

Arrays are quite a bit different than regular values in C/C++. You cannot return several of them from a function. The compiler was expecting a number between those brackets, seeing as it was looking for an integer to return.

Also keep in mind that arrays are not passed by value (using copies of its arguments) they are passed by reference (using the variables the calling function uses). That is to say, any change you make to items in the array in a function will be reflected in the same array that the calling function passed into it - the fallout of which is that you don't have to return the array at all! You can make changes to it in a function, and it gets changed as far as the calling function can tell. So we can rewrite your naughty function as this:

Code: [Select]
//takes an array and appends the current distance at the end of it, moving all values and deleting the first
void AppendDistance (int dd[], int arrayVals){
// dd is being passed by reference - any change we make here will be reflected in the calling function.
     int i = 0;

     for(i=0;i<arrayVals;i++){                  //should this be i<arrayVals or i<=arrayVals
           if (i=1){
                 dd[1]=dd[2];
           }
           else if (i=arrayVals){
                 dd[i] = GetDistance();
           }
           else{
           dd[i]=dd[i+1];
           }
      }
        // Don't return anything, since we've already changed dd, and the calling function will know about it.
}


I hope that helps you understand why it didn't quite work the first time!  ;)  If you're new to C(++), it might be a good idea to find a couple tutorials on arrays, and pointers as well. They're actually quite closely related, and knowing a bit about pointers will help you return arrays from functions if you need to. (:

cacb

Quote
Also keep in mind that arrays are not passed by value (using copies of its arguments) they are passed by reference (using the variables the calling function uses). That is to say, any change you make to items in the array in a function will be reflected in the same array that the calling function passed into it


This is almost correct  ;) . In C and C++ "an array is a pointer". In this case an array was passed as parameter, i.e. a pointer was passed ---- that pointer is passed by value and not by reference.

// a function taking a single integer by value
void func1(int by_value) {}

// a function taking a single integer by reference
void func2(int& by_ref) {}

// a function taking a single integer by pointer (the pointer is passed by value)
void func3(int* by_pointer) {}

// a function taking a single integer by pointer (the pointer is passed by reference)
void func4(int*& by_pointer_ref) {}

// function taking an array (=pointer by value) and length of array (as int by value)
void func5(int array[], int arrayVals){}

// function taking a pointer (=array) and length of array (as constant int by reference)
void func6(int* array, const int& arrayVals){}

::)



MysteriousAges

Heh. My long-winded version of my post had that. >_<;

kBit

#5
Apr 07, 2008, 03:20 am Last Edit: Apr 08, 2008, 01:42 am by kBit Reason: 1
DANGER!  :o

The way you are coding will lead to overrunning your arrays. You will read/write the next variable after this one and/or hose your return stack. And in your summing, you might be adding an extra (possibly undefined) value.

You only get away with it in this code (and I'm not sure that you are getting away with it - in one place you call a function with sampSize + 1)  because you made your array 1 more than your sampleSize. But they are not connected. What if you later modify one and forget the other?

This will help:

note: no "=" and no semicolon on the define line:
Code: [Select]

#define SonarSamps  10
int distances[SonarSamps];


Remember, an array in C goes from 0..size - 1;

Code: [Select]

 for (i=0;i<=arrayVals;i++){
   sum = array[i]+sum;
 }


should be:

Code: [Select]

 for (i=0;i<arrayVals;i++){
   sum = array[i]+sum;
 }


And

Code: [Select]

//Takes a sample from the Sonar  and appends it to the distances array
 i=0;
 for(i=0;i<=SonarSamps;i++){
   if (i==0){
     distances[0]=distances[1];
   }
   else if(i==SonarSamps){
     distances[i] = GetDistance();
   }
   else{
     distances[i]=distances[i+1];
   }
 }


Should be:

Code: [Select]

//Takes a sample from the Sonar  and appends it to the distances array
 i=0;
 for(i=0;i<SonarSamps;i++){
   if (i==0){
     distances[0]=distances[1];
   }
   else if(i==SonarSamps){
     distances[i] = GetDistance();
   }
   else{
     distances[i]=distances[i+1];
   }
 }


Also, way too much wasted CPU time moving values (this part):
Code: [Select]

     distances[i]=distances[i+1];


No need to move the data. Just move the insertion point:
Code: [Select]

distances[i++] = GetDistance();
if(i == SonarSamps)
  i = 0;


Go Up