Pages: [1] 2   Go Down
Author Topic: dynamic array? or varrying the size of the array based on something?  (Read 1252 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

is it possible?

My project measures wheel speed by measuring time between interrupts.  At low speed (<20hz) its fairly accurate and i can use a small array of 1 or 2 readings for fast response; but at 800hz and up i need a bigger array (8-10) to smooth out the readings.

is it possible to have an array that changes size dynamically?    if i tru declaring the array as anything but constant i get errors.

right now the ISR changes the position of itself in the array and i want to keep that code small so i dont possibly miss any other interupts.

anyway here is my in progress code:

Code:
const int SnumRead = 8;
const int pot = A0;

volatile unsigned long pulse0[SnumRead];
volatile unsigned long pIndex0 = 0;
volatile unsigned long nowPulse0 = 0;
volatile unsigned long lastPulse0 = 0;
volatile unsigned long i0, sum0, average0 = 0;
float rate0;

volatile unsigned long pulse1[SnumRead];
volatile unsigned long pIndex1 = 0;
volatile unsigned long nowPulse1 = 0;
volatile unsigned long lastPulse1 = 0;
volatile unsigned long i1, sum1, average1 = 0;
float rate1;

volatile unsigned long pulse2[SnumRead];
volatile unsigned long pIndex2 = 0;
volatile unsigned long nowPulse2 = 0;
volatile unsigned long lastPulse2 = 0;
volatile unsigned long i2, sum2, average2 = 0;
float rate2;

volatile unsigned long pulse3[SnumRead];
volatile unsigned long pIndex3 = 0;
volatile unsigned long nowPulse3 = 0;
volatile unsigned long lastPulse3 = 0;
volatile unsigned long i3, sum3, average3 = 0;
float rate3;

float slip;
float threshold;
float overslip;
float overslipscale = 25;


void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  attachInterrupt(0, count0, FALLING);
  attachInterrupt(1, count1, FALLING);
  attachInterrupt(2, count2, FALLING);
  attachInterrupt(3, count3, FALLING );
}

void loop() {
  average0 = 0;
  sum0= 0;
  for (i0 = 0; i0 <= SnumRead; i0++)
  {
    sum0 +=pulse0[i0];
  }
  average0 = sum0 / SnumRead;
  rate0 =  (float)1000000 / average0;
 
 
  average1 = 0;
  sum1= 0;
  for (i1 = 0; i1 <= SnumRead; i1++)
  {
    sum1 +=pulse1[i1];
  }
  average1 = sum1 / SnumRead;
  rate1 =  (float)1000000 / average1;
 
 
 
  average2 = 0;
  sum2= 0;
  for (i2 = 0; i2 <= SnumRead; i2++)
  {
    sum2 +=pulse2[i2];
  }
  average2 = sum2 / SnumRead;
  rate2 =  (float)1000000 / average2;
 
 
  average3 = 0;
  sum3= 0;
  for (i3 = 0; i3 <= SnumRead; i3++)
  {
    sum3 +=pulse3[i3];
  }
  average3 = sum3 / SnumRead;
  rate3 =  (float)1000000 / average3;


  threshold = analogRead(pot);
  threshold = threshold / 48.71;
  slip = max(rate0, rate1) / max(rate2, rate3);
  slip = 100 * (slip - 1);
  overslip = slip - threshold;
  if (overslip < 0)
  {
  overslip = 0;
  }
  else if (overslip > overslipscale)
  {
  overslip = overslipscale;
  }
 
  Serial.println("");
  Serial.print(rate0,2);
  Serial.print(" / ");
  Serial.print(rate1,2);
  Serial.print(" / ");
  Serial.print(rate2,2);
  Serial.print(" / ");
  Serial.print(rate3),2;
  Serial.print(" --- ");
  Serial.print(threshold),2;
  Serial.print(" / ");
  Serial.print(slip),2;
  Serial.print(" / ");
  Serial.print(overslip),2;
 
  if (threshold < 21)
  {
  overslip = map(overslip, 0, overslipscale, 0, 255);
  analogWrite(11, overslip);
  digitalWrite(13, HIGH);
  }
  else
  {
  analogWrite(11, 0);
  digitalWrite(13, LOW);
  }
 
 
  delay(5);
}

void count0()
{
  nowPulse0 = micros();
  pulse0[pIndex0] = nowPulse0 - lastPulse0;
  pIndex0++;
  if (pIndex0 > SnumRead)
    pIndex0 = 0;
  lastPulse0 = nowPulse0;
  }
void count1()
{
  nowPulse1 = micros();
  pulse1[pIndex1] = nowPulse1 - lastPulse1;
  pIndex1++;
  if (pIndex1 > SnumRead)
    pIndex1 = 0;
  lastPulse1 = nowPulse1;
  nowPulse1 = 0;
}
void count2()
{
  nowPulse2 = micros();
  pulse2[pIndex2] = nowPulse2 - lastPulse2;
  pIndex2++;
  if (pIndex2 > SnumRead)
    pIndex2 = 0;
  lastPulse2 = nowPulse2;
  nowPulse2 = 0;
}
void count3()
{
  nowPulse3 = micros();
  pulse3[pIndex3] = nowPulse3 - lastPulse3;
  pIndex3++;
  if (pIndex3 > SnumRead)
    pIndex3 = 0;
  lastPulse3 = nowPulse3;
  nowPulse3 = 0;
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46113
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
right now the ISR changes the position of itself in the array and i want to keep that code small so i dont possibly miss any other interupts.
No, it doesn't. The ISR is a function. It is not an array element, so it can't move itself in the array.

There are ways to dynamically define arrays. You are advised not to use them. The Arduino (328-based, anyway) has little memory. Fragmenting that doing dynamic memory allocation is not advised. Clearly, you are not using a 328 based Arduino, since it does not have 4 interrupt pins. Still, small, static arrays are best.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8453
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can, but reallocating memory is probably not for a beginner. Just allocate space for the largest eventuality and save yourself some heartache.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
is it possible?

Yes.

Quote
My project measures wheel speed by measuring time between interrupts.  At low speed (<20hz) its fairly accurate and i can use a small array of 1 or 2 readings for fast response; but at 800hz and up i need a bigger array (8-10) to smooth out the readings.

You do not need such (large) arrays to measure wheel speed. Maybe you want to rethink your approach instead.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11176
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just allocate space for the largest eventuality and save yourself some heartache.

Sounds like the best idea to me. I guess you are using the array as a FIFO buffer to work out a rolling average. In that case you would presumably be using it as a circular buffer. You can change the capacity of a circular buffer very easily, just by subtracting a value from the capacity calculation to prevent the buffer from filling beyond a threshold. If it's really just being used as an array then of course you can change the effective size even more easily, just pretend the array is the size you need and ignore any excess elements.

A less precise but much easier approach would be to calculate a decaying average, in which case you don't need to remember historical results at all.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
right now the ISR changes the position of itself in the array and i want to keep that code small so i dont possibly miss any other interupts.
No, it doesn't. The ISR is a function. It is not an array element, so it can't move itself in the array.

There are ways to dynamically define arrays. You are advised not to use them. The Arduino (328-based, anyway) has little memory. Fragmenting that doing dynamic memory allocation is not advised. Clearly, you are not using a 328 based Arduino, since it does not have 4 interrupt pins. Still, small, static arrays are best.

what do you mean it doesnt?

Code:
 nowPulse2 = micros();
  pulse2[pIndex2] = nowPulse2 - lastPulse2;
  pIndex2++;
  if (pIndex2 > SnumRead)
    pIndex2 = 0;
  lastPulse2 = nowPulse2;
  nowPulse2 = 0;

it seems like its populating the various slots in the array.  if i change the sample size it makes a difference.


Quote
is it possible?

Yes.

Quote
My project measures wheel speed by measuring time between interrupts.  At low speed (<20hz) its fairly accurate and i can use a small array of 1 or 2 readings for fast response; but at 800hz and up i need a bigger array (8-10) to smooth out the readings.

You do not need such (large) arrays to measure wheel speed. Maybe you want to rethink your approach instead.


care to elaborate on this?  i need fairly high resolution (measure slip in 1/10 of a percent) so i'm measruring time between pulses.  the way i have it setup works great but at high speed the small size of the array leads to some big jumps; upping the size makes it happier.

/edit:  my first attempt was just counting pulses but at low speed the reaction was way too slow; i need to update the output based on slip at least every 10ms (100hz). even at 20hz there wasn't enough pulses to have enough resolution to have useful data.  this timing of pullses works much better.



i think i have an idea though;  leave the array with 8 spaces but at low speed only use the first 2 then at higher speed maybe 4 then highest speed use all 8.  i'll have to try it but i think it'll work better than trying to reallocate memory
« Last Edit: December 11, 2012, 11:53:38 pm by computerjlt » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My project measures wheel speed by measuring time between interrupts.

This might help:

http://gammon.com.au/forum/?id=11504

Two techniques are described near the start of that thread. Counting (getting the frequency directly) and measuring the period and inverting it. One is better for low frequencies and one is better for high frequencies.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8453
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS commented on this
Quote
the ISR changes the position of itself in the array

You are now saying this
Quote
populating the various slots in the array.  if i change the sample size it makes a difference.

Two totally different things.

Quote
eave the array with 8 spaces but at low speed only use the first 2 then at higher speed maybe 4 then highest speed use all 8.  i'll have to try it but i think it'll work better than trying to reallocate memory
Sounds like a better plan.

_____
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My project measures wheel speed by measuring time between interrupts.

This might help:

http://gammon.com.au/forum/?id=11504

Two techniques are described near the start of that thread. Counting (getting the frequency directly) and measuring the period and inverting it. One is better for low frequencies and one is better for high frequencies.

the frequencies i'm dealing with are much slower; from about 10hz-2000hz so i'd have to have a huge window for it to count in which would make the response of the output unuseable.  the method i have works and with enough smoothing seems to work well.

i played with the variable sized index for a 8 space array and got it to work but i think my math is broke somewhere. i'll have to spend more time on it.

PaulS commented on this
Quote
the ISR changes the position of itself in the array

You are now saying this
Quote
populating the various slots in the array.  if i change the sample size it makes a difference.

Two totally different things.

Quote
eave the array with 8 spaces but at low speed only use the first 2 then at higher speed maybe 4 then highest speed use all 8.  i'll have to try it but i think it'll work better than trying to reallocate memory
Sounds like a better plan.

_____
Rob

i meant the latter; the isr changes the index position for the array or resets it to 0 if +1 is too many
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8453
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
i meant the latter;
Us engineers are a pedantic lot who tend to take things literally smiley Part of the job description I suppose.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
i meant the latter;
Us engineers are a pedantic lot who tend to take things literally smiley Part of the job description I suppose.

______
Rob

understandable lol

i'm still very new to all this so all the proper nomenclature eludes me :-/
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

anyone have any bright ideas why my math isn't working?   if i go over 30hz the rate0 jumps.  i know its adding another value in there but if i fix the math in the loop (SnumRread + 1) then its wrong if i go under 30hz.....


here is the code thats not working:
Code:
const int SnumReadCC = 5;
volatile int SnumRead = 1;
const int pot = A0;

volatile unsigned long pulse0[SnumReadCC];
volatile unsigned long pIndex0 = 0;
volatile unsigned long nowPulse0 = 0;
volatile unsigned long lastPulse0 = 0;
volatile unsigned long nxtLastPulse0 = 0;
volatile unsigned long i0, sum0, average0 = 0;
float rate0;

volatile unsigned long pulse1[SnumReadCC];
volatile unsigned long pIndex1 = 0;
volatile unsigned long nowPulse1 = 0;
volatile unsigned long lastPulse1 = 0;
volatile unsigned long i1, sum1, average1 = 0;
float rate1;

volatile unsigned long pulse2[SnumReadCC];
volatile unsigned long pIndex2 = 0;
volatile unsigned long nowPulse2 = 0;
volatile unsigned long lastPulse2 = 0;
volatile unsigned long i2, sum2, average2 = 0;
float rate2;

volatile unsigned long pulse3[SnumReadCC];
volatile unsigned long pIndex3 = 0;
volatile unsigned long nowPulse3 = 0;
volatile unsigned long lastPulse3 = 0;
volatile unsigned long i3, sum3, average3 = 0;
float rate3;

float slip;
float threshold;
float overslip;
float overslipscale = 25;


void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  attachInterrupt(0, count0, FALLING);
  attachInterrupt(1, count1, FALLING);
  attachInterrupt(2, count2, FALLING);
  attachInterrupt(3, count3, FALLING );
}

void loop() {
  average0 = 0;
  sum0= 0;
  for (i0 = 0; i0 <= (SnumRead); i0++)
  {
    sum0 = sum0 + pulse0[i0];
  }
  average0 = sum0 / (SnumRead + 1);
  rate0 =  (float)1000000 / average0;
 
 
  average1 = 0;
  sum1= 0;
  for (i1 = 0; i1 <= (SnumRead + 1); i1++)
  {
    sum1 +=pulse1[i1];
  }
  average1 = sum1 / (SnumRead + 1);
  rate1 =  (float)1000000 / average1;
 
 
 
  average2 = 0;
  sum2= 0;
  for (i2 = 0; i2 <= (SnumRead + 1); i2++)
  {
    sum2 +=pulse2[i2];
  }
  average2 = sum2 / (SnumRead + 1);
  rate2 =  (float)1000000 / average2;
 
 
  average3 = 0;
  sum3= 0;
  for (i3 = 0; i3 <= (SnumRead + 1); i3++)
  {
    sum3 +=pulse3[i3];
  }
  average3 = sum3 / (SnumRead + 1);
  rate3 =  (float)1000000 / average3;


  threshold = analogRead(pot);
  threshold = threshold / 48.71;
  slip = max(rate0, rate1) / max(rate2, rate3);
  slip = 100 * (slip - 1);
  overslip = slip - threshold;
  if (overslip < 0)
  {
  overslip = 0;
  }
  else if (overslip > overslipscale)
  {
  overslip = overslipscale;
  }
 
  Serial.println("");
  Serial.print(rate0,2);
  Serial.print(" / ");
  Serial.print(rate1,2);
  Serial.print(" / ");
  Serial.print(rate2,2);
  Serial.print(" / ");
  Serial.print(rate3),2;
  Serial.print(" --- ");
  Serial.print(threshold),2;
  Serial.print(" / ");
  Serial.print(slip),2;
  Serial.print(" / ");
  Serial.print(overslip),2;
 
  if (threshold < 21)
  {
  overslip = map(overslip, 0, overslipscale, 0, 255);
  analogWrite(11, overslip);
  digitalWrite(13, HIGH);
  }
  else
  {
  analogWrite(11, 0);
  digitalWrite(13, LOW);
  }

  if (rate0 <= 30)
  {
  SnumRead = 1;
  }
  else if (rate0 > 30)
  {
  SnumRead = 5;
  }

  Serial.print(" / ");
  Serial.print(SnumRead); 
  delay(5);
}

void count0()
{
  nowPulse0 = micros();
  pulse0[pIndex0] = nowPulse0 - lastPulse0;
  pIndex0++;
  if (pIndex0 > (SnumRead))
    pIndex0 = 0;
  nxtLastPulse0 = lastPulse0;
  lastPulse0 = nowPulse0;
  }
void count1()
{
  nowPulse1 = micros();
  pulse1[pIndex1] = nowPulse1 - lastPulse1;
  pIndex1++;
  if (pIndex1 > (SnumRead + 1))
    pIndex1 = 0;
  lastPulse1 = nowPulse1;
  nowPulse1 = 0;
}
void count2()
{
  nowPulse2 = micros();
  pulse2[pIndex2] = nowPulse2 - lastPulse2;
  pIndex2++;
  if (pIndex2 > (SnumRead + 1))
    pIndex2 = 0;
  lastPulse2 = nowPulse2;
  nowPulse2 = 0;
}
void count3()
{
  nowPulse3 = micros();
  pulse3[pIndex3] = nowPulse3 - lastPulse3;
  pIndex3++;
  if (pIndex3 > (SnumRead + 1))
    pIndex3 = 0;
  lastPulse3 = nowPulse3;
  nowPulse3 = 0;
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i think i fixed it;  i removed the = sign in my for loop


Code:
average0 = 0;
  sum0= 0;
  for (i0 = 0; i0 <= (SnumRead); i0++)
  {
    sum0 = sum0 + pulse0[i0];
  }
  average0 = sum0 / SnumRead;
  rate0 =  (float)1000000 / average0;
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i still dont think its quite right;  SnumRead is set to 5; which is 6 spots in an array.

for that bit of code in the loop i should have a sample size of 6 samples but then to figure the avage its dividing by SnumRead which is set to 5. but the frequency is right (output matches my function gen)?

hmmmmmmmmm  anyone have some insight?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46113
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  for (i0 = 0; i0 <= (SnumRead); i0++)
Why are there parentheses around SnumRead?

Code:
  for (i1 = 0; i1 <= (SnumRead + 1); i1++)
Why does this loop loop a different number of times?

You really need to start using arrays and functions. Nothing about those 4 blocks of code (expect the bizarre discrepancy in the number of times each loops) is different, except which array is read from. There is, for instance, absolutely no reason to use four different loop index variables or 4 different accumulators.

Casting 1000000 to a float may not be achieving the result you expect. Using 1000000.0 instead would eliminate the need for the cast. Also, the compiler knows that a literal with a decimal place in it is not an int. Without that decimal point, it assumes that the value IS an int (which it isn't). What happens when that value is cast to a float is anyone's guess.

I wouldn't write code that requires guessing. Your mileage may vary.

Your ISRs are theoretically all firing at different times. Yet, SnumRead is the same for all 4 situations. Why?
Logged

Pages: [1] 2   Go Up
Jump to: