howto-dynamic array (size determined by pot value)

hey
i’m adapting the “smoothing” sketch that comes with the arduino 0018 for my midi controller, which is coming along very nicely.

i’m using the smoothing function to average a series of readings from my Parallax PING sensor. implementing the sketch into my own code was easy. now, however, i have a more complicated problem.

i want to be able to determine the size of the array (and thus, the size of the pool of averaged numbers) using a potentiometer.

so far, i have been unable to tell how to create an array whose size i can control at whim. is an array’s size fixed upon program initialization? the smoothing code (which i’ve pasted below) begins with a const int setting “numReadings.” this is the value which i’d like to be able to manipulate in realtime, so that i may shorten/lengthen the array depending on how snappy i want my PING to respond.

unfortunately, when i change the const int to just a regular old “int” the code won’t compile.

const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = 0;

void setup()
{
  // initialize serial communication with computer:
  Serial.begin(9600);                   
  // initialize all the readings to 0: 
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;          
}

void loop() {
  // subtract the last reading:
  total= total - readings[index];         
  // read from the sensor:  
  readings[index] = analogRead(inputPin); 
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array:  
  index = index + 1;                    

  // if we're at the end of the array...
  if (index >= numReadings)              
    // ...wrap around to the beginning: 
    index = 0;                           

  // calculate the average:
  average = total / numReadings;         
  // send it to the computer (as ASCII digits) 
  Serial.println(average, DEC);               
}

the workaround i've had is to create a series of however many different sized arrays i want and use the pot to select which one is being used.

this is not ideal as the clutter of 17 arrays would be ungainly, and i feel like there must be a better way to do it.

The maximum value that a potentiometer will return is 1023. You could create an array of fixed size (1024), and use the potentiometer reading to define how many of those values to actually use.

You might run into memory limits with this large an array, though.

You could modify the algorithm to not use an array at all. The average value is the sum of the values divided by the number of values. If the pot is controlling the number of values, the sum can be computed as the values are read, rather than storing the values in an array for later addition.

Overflow could be a problem, but, if you know how many values there are going to be (by reading the pot, sum up (reading/numValues), rather than summing up reading, then dividing.

Summing all the values and then dividing would be faster, since there is only division, but the limiting factor in your application is going to be taking the Ping))) readings, not dividing the results.

An unsigned long variable could sum 4 198 404 x 10 bit readings, so if you took 1000 samples a second, you could average nearly one hour and ten minutes’ samples before overflow.

I too think it would be easier to just accumulate the sensor A/D readings into a unsigned long variable and use another variable to hold the pot reading a/d reading. You then just start with a cleared accumulated sum and read the sensor the amount of times of the pot variable value and then divide the accumulated sum by the pot value variable. You can then zero the accumulator, take a pot reading for the next cycle. Lather and repeat. That will use a lot less ram and probably execute faster. That would allow for up to 1023 sensor value averaging. You would also have to make sure you don't use a pot value of zero, so give it a if test and make it 1 or 2 if it's a zero.

Lefty

it certainly does sound easier to stay away from the array in this case.

retrolefty, thanks for summing it up i have a question.

how can i "read the sensor the amount of times of the pot variable" without using an array? ie, how can i dictate to arduino how many times it needs to read a pin before doing further math and spitting back a value?

finally, this is a PING sensor whose data i will be averaging, not an analog input...the values we're talking about are between 350 and 4000. longs are definitely the way to go here, as i embarrassed myself for a while using an int and wondered why my output value was nonsense (overflow)

thanks for your comments, everyone nym

how can i dictate to arduino how many times it needs to read a pin before doing further math and spitting back a value?

limit = analogRead (smoothPot);
for (int i = 0, sum = 0; i < limit; i++) {
  sum+=analogRead (sensorInput);
}
sum /= limit;  // average in "limit"

how can i "read the sensor the amount of times of the pot variable" without using an array? ie, how can i dictate to arduino how many times it needs to read a pin before doing further math and spitting back a value?

Well the pot value is the number of reading you wish to accumulate into a unsigned long. So use the pot value as a index value in a for loop where you keep adding sensor readings into the accumulator variable until the for loop completes and then you divide the unsigned long by the pot value.

Lefty