vL53LoX Singl Average reading

Hello There, I am trying to use the sensor to take 4 different readings and record then a 128x64 OLED, each reading is set by (switch case) 4 times where sensor is reading continuously and overwrite readings 2,3,4 which overlaps, ideally I would like to take a sample of 4 readings and average them in each class state, the display should hold each reading untill reser at the end of sketch.
I have been trying to get everything working for months now and still not quite there, I am a 76 year old trying to learn new tricks.
Your help getting the coding right eould be Greatly Appreciated.
Duggy

/* This example shows how to get single-shot range
 measurements from the VL53L0X. The sensor can optionally be
 configured with different ranging profiles, as described in
 the VL53L0X API user manual, to get better performance for
 a certain application. This code is based on the four
 "SingleRanging" examples in the VL53L0X API.

 The range readings are in units of mm. */

#include <Wire.h>
#include <VL53L0X.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NewPing.h>

#define laser 3
#define button 6                    // Pushbutton on D3
#define resetPin  7
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
VL53L0X sensor;

int state = 0;                     //  integer to hold current state
int old = 0;                       //  interger to hold last state
int buttonPoll = 0;               //  intereger to hold button state

// Uncomment this line to use long range mode. This
// increases the sensitivity of the sensor and extends its
// potential range, but increases the likelihood of getting
// an inaccurate reading because of reflections from objects
// other than the intended target. It works best in dark
// conditions.

//#define LONG_RANGE


// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed

//#define HIGH_SPEED
#define HIGH_ACCURACY

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()
{
  Serial.begin(115200);
  Wire.begin();
     digitalWrite(resetPin,HIGH);
   pinMode(resetPin,OUTPUT);

   pinMode(laser,OUTPUT);
   digitalWrite(laser,LOW);
   pinMode(button,INPUT);           // button set as INPUT    
 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
 
  sensor.setTimeout(500);
  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
  }

#if defined LONG_RANGE
  // lower the return signal rate limit (default is 0.25 MCPS)
  sensor.setSignalRateLimit(0.1);
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif

//#if defined HIGH_SPEED
  // reduce timing budget to 20 ms (default is about 33 ms)
  //sensor.setMeasurementTimingBudget(20000);
//#elif defined HIGH_ACCURACY
  // increase timing budget to 200 ms
  //sensor.setMeasurementTimingBudget(200000);
//#endif

  display.setTextSize(3);
  display.setTextColor(WHITE);
       display.clearDisplay();
       display.setCursor(20,20);
   display.print("READY");
   display.display();
     //Serial.print(sensor.readRangeSingleMillimeters());
}

void loop()
{
   digitalWrite(resetPin,HIGH);
   display.setTextSize(2);
  

  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

                              // De Bouncing routine to read button
   buttonPoll = digitalRead(button);       // Poll the state of the button
   if (buttonPoll == 1){                    //  Chech to see if it has been pressed
       delay(500);                          // wait 50 Ms
       buttonPoll = digitalRead(button);   //Poll button again
       if (buttonPoll == 0){               // if it is 0 considered one press
        //Serial.print("button press 1 ");
        state = old + 1;                   // Increase state by 1
               }}
       else{                               // if button has not been pressed
        delay (100);                       // Wait 100 ms   

  Serial.println();
     switch(state) {                          // React to buttonPress and state
     case 1:                               // If state is 1
     Serial.println ("Case 1");
     digitalWrite(laser,HIGH);
      display.clearDisplay();
      display.setCursor(0,0);
      display.print("1 - ");
      display.setCursor(40,0);
      display.print(sensor.readRangeSingleMillimeters());
      display.setCursor(95,0);
      display.print("mm");
      display.display();
     delay(100);

     old = state;                          // Set old state as current state
     break;
         
    case 2:                               // If state is 1
     Serial.println ("Case 2");
      //display.clearDisplay();
      display.setCursor(0,16);
      display.print("2 - ");
      display.setCursor(40,16);
      display.print(sensor.readRangeSingleMillimeters());
      display.setCursor(95,16);
      display.print("mm");
      display.display();
     old = state;                          // Set old state as current state
     break;

     case 3:                               // If state is 1
      
      Serial.println ("Case 3");
      //display.clearDisplay();
      display.setCursor(0,34);
      display.print("3 - ");
      display.setCursor(40,34);
      display.print(sensor.readRangeSingleMillimeters());
      display.setCursor(95,34);
      display.print("mm");
      display.display();

     old = state;                          // Set old state as current state
     break; 
     
    case 4:                               // If state is 1
          Serial.println ("Case 4");
      //display.clearDisplay();
      display.setCursor(0,52);
      display.print("4 - ");
      display.setCursor(40,52);
      display.print(sensor.readRangeSingleMillimeters());
      display.setCursor(95,52);
      display.print("mm");
      display.display();
     old = state;                          // Set old state as current state
     break;
     
     case 5:                               // If state is 1
  
    Serial.println("Case 5");
     display.clearDisplay(); 
     display.setCursor(30,20);
     display.print("RESET");
     display.display();
     
     delay(1000);
     digitalWrite(resetPin,LOW);
     delay(1000);
     digitalWrite(laser,LOW);
     Serial.println ("END");

     default:                               // if state is not 1,2,3,4

     delay(1000);

    // delay(5000);
     digitalWrite(resetPin,HIGH);
}}}

Hello.

Can you provide more details on what exactly are you having trouble with? Can you simplify your program and post the simplest possible program that should work but doesn’t, and describe the expected behavior and the actual behavior?

- Amanda

Hi Amanda.
I am trying to take 4 different measurements and display them on the OLED, each measurement is measured by a momentary button switch,The display should look like this after switch case (4),
1 - 254 mm
2 - 840 mm
3- 1015 mm
4 - 900 mm
then on switch case (5) reset, My trouble is in each case 1 - 4 the measurement is looping then reading 2 on the OLED wants to display 1 measurement on top of the other, ideally I would like to take an average of each case and display it as a single measuremet.
I have cleaned up the sketch, I hope you can follow it. also included a schematic.
Regards
Doug

/* This example shows how to get single-shot range
  measurements from the VL53L0X. The sensor can optionally be
  configured with different ranging profiles, as described in
  the VL53L0X API user manual, to get better performance for
  a certain application. This code is based on the four
  "SingleRanging" examples in the VL53L0X API.

  The range readings are in units of mm. */

#include <Wire.h>
#include <VL53L0X.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NewPing.h>
#define laser 3
#define button 6                    // Pushbutton on D3
#define resetPin  7
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
VL53L0X sensor;

int state = 0;                     //  integer to hold current state
int old = 0;                       //  interger to hold last state
int buttonPoll = 0;               //  intereger to hold button state

#define HIGH_ACCURACY
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()
{
  Serial.begin(115200);
  Wire.begin();
  digitalWrite(resetPin, HIGH);
  pinMode(resetPin, OUTPUT);
  pinMode(laser, OUTPUT);
  digitalWrite(laser, LOW);
  pinMode(button, INPUT);          // button set as INPUT
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  sensor.setTimeout(500);
  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
  }
  sensor.setSignalRateLimit(0.1);
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
//#endif

  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setCursor(20, 20);
  display.print("READY");
  display.display();
}
void loop()
{
  digitalWrite(resetPin, HIGH);
  display.setTextSize(2);

  if (sensor.timeoutOccurred()) {
    Serial.print(" TIMEOUT");
  }

  // De Bouncing routine to read button
  buttonPoll = digitalRead(button);       // Poll the state of the button
  if (buttonPoll == 1) {                   //  Chech to see if it has been pressed
    delay(500);                          // wait 50 Ms
    buttonPoll = digitalRead(button);   //Poll button again
    if (buttonPoll == 0) {              // if it is 0 considered one press

      state = old + 1;                   // Increase state by 1
    }
  }
  else {                              // if button has not been pressed
    delay (100);                       // Wait 100 ms

    Serial.println();
    switch (state) {                         // React to buttonPress and state
      case 1:                               // If state is 1
        digitalWrite(laser, HIGH);
        display.clearDisplay();
        display.setCursor(0, 0);
        display.print("1 - ");
        display.setCursor(40, 0);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 0);
        display.print("mm");
        display.display();
        delay(100);

        old = state;                          // Set old state as current state
        break;

      case 2:                               // If state is 1
        display.setCursor(0, 16);
        display.print("2 - ");
        display.setCursor(40, 16);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 16);
        display.print("mm");
        display.display();
        old = state;                          // Set old state as current state
        break;

      case 3:                               // If state is 
        display.setCursor(0, 34);
        display.print("3 - ");
        display.setCursor(40, 34);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 34);
        display.print("mm");
        display.display();

        old = state;                          // Set old state as current state
        break;

      case 4:                               // If state is 1
        Serial.println ("Case 4");
        //display.clearDisplay();
        display.setCursor(0, 52);
        display.print("4 - ");
        display.setCursor(40, 52);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 52);
        display.print("mm");
        display.display();
        old = state;                          // Set old state as current state
        break;

      case 5:                               // If state is 1

        Serial.println("Case 5");
        display.clearDisplay();
        display.setCursor(30, 20);
        display.print("RESET");
        display.display();

        delay(1000);
        digitalWrite(resetPin, LOW);
        delay(1000);
        digitalWrite(laser, LOW);
        Serial.println ("END");

      default:                               // if state is not 1,2,3,4

        delay(1000);

        // delay(5000);
        digitalWrite(resetPin, HIGH);
    }
  }
}
/* This example shows how to get single-shot range
  measurements from the VL53L0X. The sensor can optionally be
  configured with different ranging profiles, as described in
  the VL53L0X API user manual, to get better performance for
  a certain application. This code is based on the four
  "SingleRanging" examples in the VL53L0X API.

  The range readings are in units of mm. */

#include <Wire.h>
#include <VL53L0X.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NewPing.h>
#define laser 3
#define button 6                    // Pushbutton on D3
#define resetPin  7
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
VL53L0X sensor;

int state = 0;                     //  integer to hold current state
int old = 0;                       //  interger to hold last state
int buttonPoll = 0;               //  intereger to hold button state

#define HIGH_ACCURACY
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()
{
  Serial.begin(115200);
  Wire.begin();
  digitalWrite(resetPin, HIGH);
  pinMode(resetPin, OUTPUT);
  pinMode(laser, OUTPUT);
  digitalWrite(laser, LOW);
  pinMode(button, INPUT);          // button set as INPUT
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  sensor.setTimeout(500);
  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
  }
  sensor.setSignalRateLimit(0.1);
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
//#endif

  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setCursor(20, 20);
  display.print("READY");
  display.display();
}
void loop()
{
  digitalWrite(resetPin, HIGH);
  display.setTextSize(2);

  if (sensor.timeoutOccurred()) {
    Serial.print(" TIMEOUT");
  }

  // De Bouncing routine to read button
  buttonPoll = digitalRead(button);       // Poll the state of the button
  if (buttonPoll == 1) {                   //  Chech to see if it has been pressed
    delay(500);                          // wait 50 Ms
    buttonPoll = digitalRead(button);   //Poll button again
    if (buttonPoll == 0) {              // if it is 0 considered one press

      state = old + 1;                   // Increase state by 1
    }
  }
  else {                              // if button has not been pressed
    delay (100);                       // Wait 100 ms

    Serial.println();
    switch (state) {                         // React to buttonPress and state
      case 1:                               // If state is 1
        digitalWrite(laser, HIGH);
        display.clearDisplay();
        display.setCursor(0, 0);
        display.print("1 - ");
        display.setCursor(40, 0);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 0);
        display.print("mm");
        display.display();
        delay(100);

        old = state;                          // Set old state as current state
        break;

      case 2:                               // If state is 1
        display.setCursor(0, 16);
        display.print("2 - ");
        display.setCursor(40, 16);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 16);
        display.print("mm");
        display.display();
        old = state;                          // Set old state as current state
        break;

      case 3:                               // If state is 
        display.setCursor(0, 34);
        display.print("3 - ");
        display.setCursor(40, 34);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 34);
        display.print("mm");
        display.display();

        old = state;                          // Set old state as current state
        break;

      case 4:                               // If state is 1
        Serial.println ("Case 4");
        //display.clearDisplay();
        display.setCursor(0, 52);
        display.print("4 - ");
        display.setCursor(40, 52);
        display.print(sensor.readRangeSingleMillimeters());
        display.setCursor(95, 52);
        display.print("mm");
        display.display();
        old = state;                          // Set old state as current state
        break;

      case 5:                               // If state is 1

        Serial.println("Case 5");
        display.clearDisplay();
        display.setCursor(30, 20);
        display.print("RESET");
        display.display();

        delay(1000);
        digitalWrite(resetPin, LOW);
        delay(1000);
        digitalWrite(laser, LOW);
        Serial.println ("END");

      default:                               // if state is not 1,2,3,4

        delay(1000);

        // delay(5000);
        digitalWrite(resetPin, HIGH);
    }
  }
}

It sounds like you might be having an issue with how your values are being displayed on the OLED, but it’s not really clear from your description. Can you explain better (maybe break the process down into steps of what you want to see and what you are seeing)? Can you post a video showing the behavior?

- Amanda

Hi Amanda.
Here is a Video download of my problem.
Regards Doug

Your video did not show in your post. Can you try posting it on a hosting site like Youtube and linking to it?

-Derrill

Hi Derrill, could you please explain how to do this also would the post on YouTube be public
Could it be done by FaceBook Messanger I have tried to do it on yuotube https://youtu.be/zbsmM2qB3tE please let me know if it works.
Doug

The link seems to work, but the video is private; can you try changing it to public?

-Derrill

Hi, I have changed the video to public, I hope it works this time
Doug

Thanks for posting the video. You probably would need to call display.clearDisplay() like you did in your first case statement. However calling that function will clear the entire screen, so you’ll need to create a variable to store the information such that it can be displayed again.

I did a quick Internet search to see if others encountered this issue and how they solved it. This thread might be helpful to you as an easy alternative solution.

- Amanda

Hi Amanda Than kyou for your reply I will try the thread and see if it works, my other main problem is the code to take 10 measurements then average them to one value and display that value, I have searched the net for averaging codes but none that I can get to work for me, could you please help with this coding as I am at wits end with this.
Cheers Doug

You can use a loop (e.g. for loop) in each case to get the average range by summing the values from sensor.readRangeSingleMillimeters() and dividing the total by ten before displaying it on your OLED. You can search for “using a for loop to average numbers in c++” on the Internet to find some examples showing how to do that.

- Amanda

Hi Amanda, I have tried to create a smaller sketch to average the reading but still running into trouble
at line 82 sumDistance=sumDistance+distance[j];
invalid types ‘int[int]’ for array subscript,
in this example I am averaging 5 readings.
Could you please correct the sketch for me I am desperate and frustrated, its probable an easy fix but I still can’t get it., with regard the display problem I have overcome it…
Many Thanks
Doug

Distance_read_Error.ino (2.3 KB)

The distance variable in your code is defined as an int, not an int array. You need to remove the square brackets and the index variable, j, like so sumDistance=sumDistance+distance;. Since it seems like you are new to programming, I strongly suggest looking at some C++ references and tutorials to get a better understanding before continuing on.

- Amanda

Hi Amanda, Thanks for your advice that part has been fixed however my other problem is as you can see in the video the average values are over lapping each other on the OLED,any suggestions on how to only get one reading to display in each switch case.
To try and explain what I am trying to acheive is in a game of Bowles where there is a white bowl (kitty/Jack) and 2 other bowles, I want to measure the distance between the white Kitty and one of the other bowles Case 1. then measure between the other Bowl and the Kitty Case 2 then the bowl with the closest distance wins, then the same applies with cases 3 and 4, case 5 resets back to start again.
and yes I am a 76 year old newby to arduino and the white matter is not as good as it used to be so your help is greatly appreciated

Apologies for the Video quality

.[ZZZZ_SSD1306_le_vl53LOX_02-12-19__COPY_ARDUINO.ino|attachment]

(upload://cgNrPjHZs17FDuZRvMzVvIlf9u2.ino) (5.9 KB)

Video: https://youtu.be/tKQgHOk4L9M

It seems like you might have missed looking at this post, which offers a possible solution to that issue. Please note we did not write the library for OLED device you are using, so we cannot offer you much help. If you need further assistance with that product, you should consider posting on Adafruit’s support forum.

- Amanda