Storing nested for.loop() results in an array

Hi -

I have a for.loop() calculating measurements taken by a single sensors but utilising two different ROI’s. It does this by taking 20 measurements on each ROI and determine the averages of both ROI’s independently, which are then stored as two variables and all seems to be working well.

I now want to change this to a nested for.loop() as I want this entire process to repeat three times and store the results in an Array rather. I get the basics of an Array but am not sure how to use that in combination with the nested for loop and not overwrite existing data. I think I have the nesting correct, it is just creating the array which I assume will hypothetically look something like this after values have been populated?

int PathTrack [6] = {10,20,40,60,80,100}

If not possible, I am happy to store them as different variables, I just do not want to overwrite the values of each iteration as I need them to determine a condition.

Below is applicable section of my code as-is;

    int M_distance;
    int M_sum_zone_0 = 0;
    int M_sum_zone_1 = 0;
   
    int number_attempts = 5;
    
    int PathTrack_array[6] = {0,0,0,0,0,0}; 
  
    Zone = 0;

 if ((sum_zone_0 <= (calibrated_zone_0 * 0.75))) {
        
         Particle.publish("Start Measuring:", PRIVATE);
    
    // measure 3 times //
    for (int k=0; k<3; k++) {   

    // take [i]-number of readings and determine average //
        for (int i=0; i<number_attempts; i++) {
    
    // increase sum of values in Zone 0 //
            distanceSensor.setIntermeasurementPeriod(55);
            distanceSensor.setDistanceModeLong();
            distanceSensor.setROI(ROI_height, ROI_width, center[0]);  // first value: height of the zone, second value: width of the zone
            delay(50);
            distanceSensor.setTimingBudgetInMs(50);
            distanceSensor.startRanging();                            //Write configuration bytes to initiate measurement
            M_distance = distanceSensor.getDistance();                  //Get the result of the measurement from the sensor
            distanceSensor.stopRanging();      
            M_sum_zone_0 = M_sum_zone_0 + M_distance;
            Zone++;
            Zone = Zone%2;

    // increase sum of values in Zone 1 //
            distanceSensor.setIntermeasurementPeriod(55);
            distanceSensor.setDistanceModeLong();
            distanceSensor.setROI(ROI_height, ROI_width, center[1]);  // first value: height of the zone, second value: width of the zone
            delay(50);
            distanceSensor.setTimingBudgetInMs(50);
            distanceSensor.startRanging();                            //Write configuration bytes to initiate measurement
            M_distance = distanceSensor.getDistance();                  //Get the result of the measurement from the sensor
            distanceSensor.stopRanging();      
            M_sum_zone_1 = M_sum_zone_1 + M_distance;
            Zone++;
            Zone = Zone%2;
            }
    
    average_zone_0 = M_sum_zone_0 / number_attempts;
    average_zone_1 = M_sum_zone_1 / number_attempts;
    Particle.publish("Zone 1: " + String(average_zone_0) + " &  Zone 2:" + String(average_zone_1), PRIVATE);  // DEBUG
    
        }
    }

I am pretty sure there might be a more efficient way of doing things, but this is what I was able to come up with :slight_smile:

Getting the results from a single iteration published seems to be working fine, just want to store them now for later processing.

Many thanks,
Friedl

I would use a two dimensional array but you can also calculate the offset.

offset:

  PathTrack[k*3 + 0] = M_sum_zone_0 / number_attempts;
  PathTrack[k*3 + 1] = M_sum_zone_1 / number_attempts;

two dimensional array:

int PathTrack[3][2];

  PathTrack[k][0] = M_sum_zone_0 / number_attempts;
  PathTrack[k][1] = M_sum_zone_1 / number_attempts;

Additionally I'd also use an array M_sum[2] and wrap that in its own for (int zone=0; zone<2; zone++). The same goes for average[2]

There is also a shorthand for

which looks a lot more like proper C/C++ :wink:

  M_sum[zone] += M_distance;

BTW, when you divide an int by another int you will always truncate the decimal portion of the result - e.g. 49 / 5 would give you 9 although the actual result would be much closer to 10.

1 Like

Hi @ScruffR -

As usual, THANK YOU, much appreciated!!

I looked into two dimensional arrays this morning, let me see whether I can get it implemented. Glad to hear I was looking in the right places at least :smile:

With regards to integer division, no problem there. As I am working with mm's and only require about 3 zones over 2000mm, I think I can afford to lose the decimals :saluting_face:

C++.....?? What's that? :rofl:

Working on improving my non-existing coding skills I promise!

Regards, Friedl.

Almost there, just something wrong :smile: Seems to be adding up the values of each iteration. none of these should exceed 2100.

EDIT: Ok, I think I go that sorted. Just want to install the sensor in the correct orientation to see whether it is working as expected. It seems to be a little to slow and is not giving me the results I hoped for. ST does have a demo where it seems to be working, but I am sure their programmers followed a much better approach in terms of the firmware :grin:

Thanks again!

1 Like

Here is one way how your code could be revamped a bit :wink:

const int numReps = 3;
const int numROIs = 2;
const int numAvg  = 5;
  
int  mDistance;
int  track[numReps][numROIs] = {0}; 
char msg[128];
...
  Particle.publish("Start Measuring:");

  memset(track, 0, sizeof(track)); // reset array 
  for (int rep=0; rep < numReps; rep++) {   
    for (int roi=0; roi < numROIs; roi++) {
      for (int avg=0; avg < numAvg; avg++) {
        distanceSensor.setIntermeasurementPeriod(55);
        distanceSensor.setDistanceModeLong();
        distanceSensor.setROI(ROI_height, ROI_width, center[roi]);  // first value: height of the zone, second value: width of the zone
        delay(50);
        distanceSensor.setTimingBudgetInMs(50);
        distanceSensor.startRanging();                             // Write configuration bytes to initiate measurement
        mDistance = distanceSensor.getDistance();                  // Get the result of the measurement from the sensor
        distanceSensor.stopRanging();      
        track[rep][roi] += mDistance;
      }
      track[rep][roi] = (track[rep][roi] + 0.5) / (float)numAvg;   // poor man's rounding
    }
    snprintf(msg, sizeof(msg), "%d\tZone 1: %4d & Zone 2: %4d", rep, track[rep][0], track[rep][1]);
    Serial.println(msg);
    Particle.publish(msg); // beware of the rate limit!!! 
  }
1 Like

Hi @ScruffR -

Haha, revamped you say... more like an "Extreme Makeover -- Particle Edition" :smile: Let me see whether I can make this work.

I managed to get my "not quite so C++ code" working but it seems slow. I am pretty sure yours will fair much better.

Thanks a million!!

1 Like

I doubt it’ll be much faster, due to the delay(50) and the two time related distanceSensor calls.
Do you really need re-set all these settings over and over?

Hi Scruff -

Well, all seems to be working - sort of.

The idea is to determine the route an object is travelling with the single sensor. This is possible using the Vl53L1 and up as it support multiple ROI’s. Of course it would be much easier using two independent sensors, but then you might have the case where you need to install the second sensor on the other side of a wall… e.g. in a door way.

Values I am getting kind of makes sense, but it might be tricky putting together an algorithm that will catch everything. With regards to the sensor settings;

I have three instances, the first one is for calibration purpose. This I need to be as accurate as possible and as it only run once during setup, there is no need for that to be as quick. This will take more samples at a larger timing budget to ensure accuracy.

The second and third instances are only split in an attempt to speed things up. The sensor is continuously measuring to determine entry into any one of the two zones. It is critical that this happens as quickly as possible.

The third instance run once and entry has been detected. This can be a little slower (i.e. more samples for more accurate readings). I have changed this to Short distance mode, reduce the timing budget to 10ms and inter-measurement to 25ms.

My guess would be that it is not needed to reset the settings all the time aside from at restart. I have just not seen any code for this sensor being used in another way so assumed this would be the case as well.

If you feel like it, here is a link to the entire code as-is. There are plenty of commented code in my attempt to get a decent result… sorry for the mess :slight_smile:

Below is the example data of item moving in opposite directions. Not sure whether my publish statement is correct thought.

Regards,
Friedl.

1 Like

For debugging I’d suggest you use USB and Serial.print() statements to prevent missing some crucial data points :wink:

In this particular case I’d preface each condition with a printout of the actual values going into the condition and the conditional expression itself to make sure the data you see in the publishes is actually the data you expect.

I’d also add some info to the publishes in order to match k values to the respective events.

BTW, there’d also be a somewhat geeky way to set your values :wink:
Due to the fact that FALSE commonly equals 0 and TRUE equals 1 you can use the boolean result as numbers.

  int ROUTE[3] = { 2,2,2 };

  ROUTE[0] -=  (PathTrack[0][0] < PathTrack[0][1]); 
  ROUTE[1] -=  (PathTrack[1][0] > PathTrack[1][1]);
  ROUTE[2] -= ((PathTrack[2][0] > PathTrack[1][0]) 
           &&  (PathTrack[2][1] > PathTrack[1][1]));

alternatively if you could live with your route numbers being 0 and 1 instead of 1 and 2 I’d write it this way

  int ROUTE[3];

  ROUTE[0] =  (PathTrack[0][0] >= PathTrack[0][1]); 
  ROUTE[1] =  (PathTrack[1][0] <= PathTrack[1][1]);
  ROUTE[2] = ((PathTrack[2][0] <= PathTrack[1][0]) 
           && (PathTrack[2][1] <= PathTrack[1][1]));

Hi Scruff -

I just found my error, hence the deleted post :smile:

I had an array called Pathtrack and a PathTrack() function. Seems I confused the wedIDE, haha. I will look at the post above, thanks!! I will copy all the code to VSC so I can use serial monitor, thanks!

1 Like

You can use the serial monitor even when the device was flashed via Web IDE?
particle serial monitor --follow would be the command

1 Like

Ah wow… I did not know that. Will have to get n 5m USB cable or climb into my ceiling to code as the device is mounted above my door :rofl:

I usually code in VSC but as this is for the Photon 2 tutorials, I thought it best to sue WebIDE?

Regards.

Good news I suppose :joy:

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.