Coding help for handling multiple arrays

Hello guys,

I have a code, which stores array of 113 values from the signal. Once the array is full, I want to detach Interrupt and perform calculations. I will create another two arrays of same size and store those values so that I can access them at the very end of calculations. I was pretty much able to store 113 points, but I am not able to do further. I am trying to get rid of arrays, well it looks like my application demands it. Is it possible to handle multiple arrays in one code? Please let me know where I have to make changes. When I try to print other values nothing shows up on screen. Thanks in advance.

float Radians[113];
float freq, rpm;
float total = 0;
float radianAvg;
float InstVariation;
float sincomp[113], coscomp[113];
float sincoeffTotal = 0, coscoeffTotal = 0;
float sincoeffavg, coscoeffavg;
float thirdOrder;
volatile boolean finishCount = false;
volatile unsigned long period = 0;
volatile unsigned int i = 0;
long copy_period;
int copy_i;
volatile unsigned long time_last;
int k;


volatile unsigned long interruptCount;
unsigned int copy_interruptCount;


void setup()
{
  Serial.begin(115200);
  Serial.println("start...");
  pinMode(32, INPUT);
  attachInterrupt(32, pulsePeriod, RISING);//interrupt on pin3
}

void loop() {
  while (1)
  {
    if (finishCount == true)
    {
      finishCount = false;//reset flag
      noInterrupts();
      // disable interrupts, make protected copy of time values
      copy_period = period;
      copy_interruptCount = interruptCount;
      interruptCount = 0;
      interrupts();
      freq = 1000000.0 / copy_period;
      rpm = freq * 0.5309;
      Radians[k] = rpm * 0.1048533; // fill the array with 113 values
      //Serial.println(Radians[k]);
    }

    if (sizeof(Radians) == 113) // once the arrray is full make calculations
    {
      k = 0;   //Reset the pointer to zero to overwrite the array
      detachInterrupt(32); // detach interrupt to do calculations
      for ( int j = 0; j <= 112; j++) { // for loop to add all the 113 values
        total += Radians[j];
        Serial.println(total);
      }

      radianAvg = total / 113; // to get the average of 113 values

// Next for loop to calculate variation of each point in array - average of the array, then calculate sin and cos 

      for ( int k = 0; k <= 112; k++) {
        InstVariation = Radians[k] - radianAvg;
        sincomp[k] = sin( k * 0.1667) * InstVariation;
        coscomp[k] = cos(k * 0.1667) * InstVariation;
        sincoeffTotal += sincomp[k];
        coscoeffTotal += coscomp[k];
      }

      sincoeffavg = sincoeffTotal / 113;
      coscoeffavg = coscoeffTotal / 113;
      thirdOrder = sqrt((sincoeffavg * sincoeffavg) + (coscoeffavg + coscoeffavg)) * 6.24; // Third Order harmonics of the resultant wave.

      //debug prints
      //Serial.println(thirdOrder);
    }
  }
}

void pulsePeriod()//simplify isr
{
  period = (micros() - time_last);
  time_last = micros();
  finishCount = true;
  interruptCount++;
}

sizeof(Radians) == 113

This will never be 113. It reports the size of the array you allocated in bytes.

You want to have a separate volatile global, possibly interruptCount, that keeps track of the number of measurements.

It looks like the “number of measurements” might be handy to keep in variable k since you’re already using it to iterate through the array with:

Radians[k] = rpm * 0.1048533;

but k isnt incremented anywhere. Where should it be? Maybe right after the above line?

If you use k, then it’d be handy to do this later on:

if (k == 113) // once the arrray is full make calculations
void loop() {
  while (1)
  {

You have a forever loop inside a forever loop. You should eliminate the while(1), it's not needed and just confuses things.

KeithRB:
sizeof(Radians) == 113

This will never be 113. It reports the size of the array you allocated in bytes.

You want to have a separate volatile global, possibly interruptCount, that keeps track of the number of measurements.

My bad I got confused with size of array. I will change it to length().

@ bdeters you are right. I need to clean up my program.

@arg The reason I used another while loop is to removed some overhead. Since, I am dealing with time critical issue.

meme:
@arg The reason I used another while loop is to removed some overhead. Since, I am dealing with time critical issue.

You should document that with a comment.

I have a code, which stores array of 113 values from the signal. Once the array is full, I want to detach Interrupt and perform calculations. I will create another two arrays of same size and store those values so that I can access them at the very end of calculations. I was pretty much able to store 113 points, but I am not able to do further. I am trying to get rid of arrays, well it looks like my application demands it. Is it possible to handle multiple arrays in one code? Please let me know where I have to make changes. When I try to print other values nothing shows up on screen. Thanks in advance.

Here is some code which loads the period data into an array within the isr. There are two arrays declared so that one can be analysed while the other is filled. There is no need to turn off the interrupts if one array can be analysed in the time it takes to fill the other. I have made the period arrays ints, but if you have the memory they can be longs.

I don’t have a Due, so I can really test, but see if this comes close to what you need

float Radians[113];
float freq, rpm;
float total = 0;
float radianAvg;
float InstVariation;
float sincomp[113], coscomp[113];
float sincoeffTotal = 0, coscoeffTotal = 0;
float sincoeffavg, coscoeffavg;
float thirdOrder;

volatile boolean finishCount = false;
volatile unsigned int period[2][113];//raw data arrays [j][k]
volatile byte j = 0;// array index within isr
volatile byte last_j; //index to process the filled array
volatile byte k = 0;// array index within isr
volatile unsigned long time_last;

//volatile unsigned long interruptCount;
//unsigned int copy_interruptCount;


void setup()
{
  Serial.begin(115200);
  Serial.println("start...");
  pinMode(32, INPUT);
  attachInterrupt(32, pulsePeriod, RISING);//interrupt on pin32
}

void loop() {
  while (1)
  {
    if (finishCount == true)
    {
      finishCount = false;//reset flag

      for (byte i = 0; i < 113; i++)
      {
        freq = 1000000.0 / period[last_j][i];//j is set in isr and is fixed for processing one or the other array
        rpm = freq * 0.5309;
        Radians[i] = rpm * 0.1048533; // fill the Radian array with 113 values
        //Serial.println(Radians[i]);
        total += Radians[i];
      }
      Serial.println(total);

      radianAvg = total / 113; // to get the average of 113 values

      // Next for loop to calculate variation of each point in array - average of the array, then calculate sin and cos

      for ( byte i = 0; i < 113; i++)
      {
        InstVariation = Radians[i] - radianAvg;
        sincomp[i] = sin(i * 0.1667) * InstVariation;
        coscomp[i] = cos(i * 0.1667) * InstVariation;
        sincoeffTotal += sincomp[i];
        coscoeffTotal += coscomp[i];
      }

      sincoeffavg = sincoeffTotal / 113;
      coscoeffavg = coscoeffTotal / 113;
      thirdOrder = sqrt((sincoeffavg * sincoeffavg) + (coscoeffavg + coscoeffavg)) * 6.24; // Third Order harmonics of the resultant wave.

      //debug prints
      //Serial.println(thirdOrder);
    }
  }
}

void pulsePeriod()
{
  period[j][k] = (micros() - time_last);
  time_last = micros();
  // finishCount = true;
  //interruptCount++;
  k++;
  if (k == 112)//113 measurements
  {
    k = 0;
    finishCount = true;
    //switch array index
    last_j = j; //index to process the completed array
    if (j == 0)
      j = 1;
    else j = 0;
  }
}
float Radians[113];
float freq, rpm;
float total = 0;
long radianAvg;
float InstVariation;
float sincomp[113], coscomp[113];
float sincoeffTotal = 0, coscoeffTotal = 0;
float sincoeffavg, coscoeffavg;
float thirdOrder;

volatile boolean finishCount = false;
volatile unsigned int period[2][113];//raw data arrays [j][k]
volatile byte j = 0;// array index within isr
volatile byte last_j; //index to process the filled array
volatile byte k = 0;// array index within isr
volatile unsigned long time_last;

//volatile unsigned long interruptCount;
//unsigned int copy_interruptCount;


void setup()
{
  Serial.begin(115200);
  Serial.println("start...");
  pinMode(32, INPUT);
  attachInterrupt(32, pulsePeriod, RISING);//interrupt on pin32
}

void loop() {
  while (1)
  {
    if (finishCount == true)
    {
      finishCount = false;//reset flag

      for (byte i = 0; i < 113; i++)
      {
        freq = 1000000.0 / period[last_j][i];//j is set in isr and is fixed for processing one or the other array
        rpm = freq * 0.5309;
        Radians[i] = rpm * 0.1048533; // fill the Radian array with 113 values
        //Serial.println(Radians[i]);
        total += Radians[i];
        Serial.println(total);
      }

      radianAvg = total / 113; // to get the average of 113 values
      //Serial.println(radianAvg);
      // Next for loop to calculate variation of each point in array - average of the array, then calculate sin and cos

      for ( byte i = 0; i < 113; i++)
      {
        InstVariation = Radians[i] - radianAvg;
        sincomp[i] = sin(i * 0.1667) * InstVariation;
        coscomp[i] = cos(i * 0.1667) * InstVariation;
        sincoeffTotal += sincomp[i];
        coscoeffTotal += coscomp[i];
      }

      sincoeffavg = sincoeffTotal / 113;
      coscoeffavg = coscoeffTotal / 113;
      thirdOrder = sqrt((sincoeffavg * sincoeffavg) + (coscoeffavg + coscoeffavg)) * 6.24; // Third Order harmonics of the resultant wave.

      //debug prints
      //Serial.println(thirdOrder);
      total = 0;
      sincoeffTotal = 0;
      coscoeffTotal = 0;
    }
  }
}

void pulsePeriod()
{
  period[j][k] = (micros() - time_last);
  time_last = micros();
  // finishCount = true;
  //interruptCount++;
  k++;
  if (k == 112)//113 measurements
  {
    k = 0;
    finishCount = true;
    //switch array index
    last_j = j; //index to process the completed array
    if (j == 0)
      j = 1;
    else j = 0;
  }
}

It pretty much does the job, But, I see inf value in the output when I am calculating the radianAvg. I made the total to zero at the end of code, Still it didn’t work. As the transition from one array to other array occurs I see inf. is there a reason for it’s occurrence?

This was the output of the total for every 113 readings

0.00
47.42
168.70
288.93
408.13
526.57
644.51
762.44
880.13
997.82
1116.26
1234.95
1354.41
1474.90
1596.44
1719.33
1843.58
1968.96
2095.47
2223.15
2352.01
2481.76
2612.74
2744.34
2876.57
3009.11
3141.96
3274.82
3407.99
3540.53
3672.45
3804.04
3934.41
4064.17
4192.73
4320.11
4446.34
4571.16
4694.86
4817.20
4938.22
5058.45
5177.65
5296.34
5414.53
5532.22
5649.91
5767.59
5885.78
6004.73
6124.44
6244.93
6366.48
6489.36
6613.62
6738.71
6865.51
6993.48
7122.34
7252.40
7383.38
7514.98
7647.21
7780.06
7913.24
8046.41
8179.58
8312.12
8444.35
8575.64
8706.00
8835.46
8964.02
9091.41
9217.63
9342.45
9466.15
9588.23
9709.51
9829.74
9948.94
10067.63
10185.57
10303.25
10420.94
10538.88
10656.82
10775.76
10895.48
11015.97
11137.51
11260.39
11384.37
11509.75
11636.55
11764.52
11893.38
12023.44
12154.42
12286.02
12418.25
12550.79
12683.64
12816.82
12949.67
13082.21
13214.44
13345.73
13476.09
13605.55
13734.11
13861.50
inf
125.94
250.76
374.46
496.80
617.82
737.79
856.99
975.43
1093.37
1210.81
1328.50
1446.18
1564.37
1683.06
1802.78
1923.27
2045.08
2168.23
2292.49
2417.86
2544.67
2672.64
2801.79
2931.86
3062.84
3194.44
3326.66
3459.52
3592.69
3725.86
3858.72
3991.26
4123.48
4254.77
4385.14
4514.60
4642.86
4769.95
4895.90
5020.71
5144.14
5266.21
5387.23
5507.20
5626.40
5744.84
5862.78
5980.47
6098.15
6215.84
6334.03
6452.98
6572.69
6693.44
6815.25
6938.41
7062.66
7188.04
7314.84
7442.81
7571.97
7702.03
7833.01
7964.61
8097.15
8230.00
8362.86
8495.72
8628.57
8761.11
8893.02
9024.31
9154.68
9284.14
9412.70
9539.79
9665.73
9790.54
9913.97
10036.32
10157.33
10277.30
10396.50
10514.94
10632.88
10750.57
10868.01
10985.95
11104.14
11223.08
11342.79
11463.55
11585.62
11708.78
11833.03
11958.69
12085.50
12213.47
12342.32
12472.69
12603.98
12735.89
12868.12
13000.97
13134.15
13267.32
13400.17
13532.71
13664.63
13795.92
13926.28
14055.74
inf

meme:
As the transition from one array to other array occurs I see inf. is there a reason for it's occurrence?

inf

that would be infinity.

I haven't looked at your code in depth, but perhaps you can tell now knowing...

I don’t understand what you are seeing, but try to type radianAvg as a float

//long radianAvg;
float radianAvg;

Perform the division as

radianAvg = total / 113.0;
float Radians[113];
float freq, rpm;
float total = 0;
long radianAvg;
float InstVariation;
float sincomp[113], coscomp[113];

Which Arduino are you using? Three arrays with 113 floats uses 1356 byes, which is more than 60% of the memory on a 328-based Arduino.

PaulS:
Which Arduino are you using? Three arrays with 113 floats uses 1356 byes, which is more than 60% of the memory on a 328-based Arduino.

I have to agree with @PaulS, you are really hogging up the resources, and you don’t need to. If you end up saving data to some device, you only need the raw data, certainly not these arrays:

float sincomp[113], coscomp[113];

This can be done similarly like this and cut the resources in half:

#define SAMPLE_SIZE 113

volatile float ArrayA[SAMPLE_SIZE];
volatile float ArrayB[SAMPLE_SIZE];

volatile float* workingArray = ArrayA;
volatile float* calculationArray = ArrayB;

volatile bool sampleComplete = false;

void setup() 
{
  Serial.begin(115200);
  Serial.println("start...");
  pinMode(32, INPUT);
  attachInterrupt(32, pulsePeriod, RISING);//interrupt on pin32
}

void loop() 
{
  if (sampleComplete)
  {
    float radians[SAMPLE_SIZE];
    float total = 0;
    for (int i = 0; i < SAMPLE_SIZE; i++)
    {
      //float freq = 1000000.0 / calculationArray[i];//j is set in isr and is fixed for processing one or the other array
      //float rpm = freq * 0.5309;
      //radians[i] = rpm * 0.1048533; // fill the Radian array with 113 values
      //total += radians[i];
      total += 1000000.0 / calculationArray[i] * 0.5309 * 0.1048533;
      //Serial.println(total);
    }
    float radianAverage = total / 113;
    float sincoeffTotal = 0;
    float coscoeffTotal = 0;
    for (int i = 0; i < SAMPLE_SIZE; i++)
    {
      float instVariation = radians[i] - radianAverage;
      sincoeffTotal += sin(i * 0.1667) * instVariation;
      coscoeffTotal += cos(i * 0.1667) * instVariation;
    }
    float sincoeffavg = sincoeffTotal / SAMPLE_SIZE;
    float coscoeffavg = coscoeffTotal / SAMPLE_SIZE;
    float thirdOrder = sqrt((sincoeffavg * sincoeffavg) + (coscoeffavg + coscoeffavg)) * 6.24; // Third Order harmonics of the resultant wave.
    
    //output your values here....
    
    sampleComplete = false;
  }
}

void pulsePeriod()
{
  static byte k = 0;// array index within isr
  static unsigned long time_last;
  uint32_t currentMicros = micros();
  workingArray[k++] = (micros() - time_last);
  time_last = currentMicros;
  if(k >= SAMPLE_SIZE - 1)
  {
    k = 0;
    workingArray = (workingArray == ArrayA? ArrayB : ArrayA);
    calculationArray = (workingArray == ArrayA? ArrayB : ArrayA);
    sampleComplete = true;
  }
}

note very few global variables. and not to mention this infinite loop in an infinite loop…

void loop() {
  while (1)
  {

cattledog:
I don’t understand what you are seeing, but try to type radianAvg as a float

I just figured it out. The error is because of array pointer.

if (k == 112)//113 measurements // change 112 to 113 it solved the problem.

@pauls and bulldogLowell I am using arduino Due.

But I will try the code you have posted.

BulldogLowell:
note very few global variables. and not to mention this infinite loop in an infinite loop…

Sorry, I have small doubt to clarify. What’s the advantage of having few global resources ? I tried to lookup but didn’t find any. Or maybe I missed it.

In this case, it cut your memory usage by half and clearly makes your program simpler.

You may be able to cut it further, I'm just not sure what data requirements really are.

Assuming you need only the summary data, it could be even simpler.

What's the advantage of having few global resources ?

Your bedroom wall is a local resource. A downtown building wall is a global resource. How much graffiti and posters and crap is on your wall? How much on a downtown building wall?

PaulS:
Your bedroom wall is a local resource. A downtown building wall is a global resource. How much graffiti and posters and crap is on your wall? How much on a downtown building wall?

Probably, the best way to explain to a guy like me. Very creative :smiley:

 if(k >= SAMPLE_SIZE - 1)
  {
    k = 0;
    workingArray = (workingArray == ArrayA? ArrayB : ArrayA);
    calculationArray = (workingArray == ArrayA? ArrayB : ArrayA);
    sampleComplete = true;
  }

Just a clarification, are you comparing the array lengths over there? are just two arrays? Cause I don't see any comparision of length.

 if(k >= SAMPLE_SIZE - 1)
  {
  }

This doesn't work for the above condition. I dont know why. For every 113th reading I am getting inf on my screen. IF I change that to

if(k >= SAMPLE_SIZE )
  {
  }

I don't see the inf value, it doesn't make sense, because that condtion is true if array holds 114 measurements.

would like to collect 113 points, and then I want arduino due to stop sensing pulses, and do processing and then output and again the process repeats. My reply #1 code seems to work but gives me spikes in the output which is effecting my output. Any ideas are appreciated.

That's easy as long as each group of 113 points don't need to have a common starting place.

You'll need to supply some raw data and output if you want us to work on the "spikes".
When do they occur? Are there multiple spikes in the 113 data points?

In the past when you just collected interval data to an array did not attempt repeat measurements did you see the spikes? Is the "spike" on the first value when the last pulse time was determined before the calculation and you are not getting a true interval for the first pulse?

In a previous thread there was some code to handle the exception of the first pulse which does not have a previous pulse for the interval calculation

it seems the output does not validate when I try to do the same thing in excel.

What do you mean by this? Does the raw interval data when passed into excel show the spikes?

You will need to spend some more time explaining the data anomalies to us in greater detail.

Sorry, I had to edit the post. I need to make few more tests to conform, The spikes occurs at the very end of array. For, example if you have 113 array. I see random values at the last location in array. I tried if statement, but, it didn't work. I will post the code tomorrow. I am thinking to perform this operation in a block by block manner instead of continuous manner.