Arduino Mea Controling a Height Sensor, Stepper Motor and LCD

Hi All, hopefully you can help this newbie.
I am working on a project where I have an Arduino Mega performing a number of functions.
The function I am stuck on right now is getting the output from a VL6180X Time Of Flight Sensor (www.adafruit.com/product/3316), control a 5v stepper motor (28BYJ-48).
The idea is that I preset an offset into the sensor reading such that zero is 20mm below the sensor, the stepper would then drive up or down (cw/ccw) depending on the reading.
I thought I could do this with “If” statements as in the code but it just seems to follow the first “If” and turn cw.
I can get the sensor to read correctly but a soon as I use If’s or While’s it all goes pear shaped.
Hopefully this makes sense, please see the code which might make it clearer:

// include the library code:
#include <Wire.h>
#include "Adafruit_VL6180X.h"
#include <Stepper.h>
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

Adafruit_VL6180X vl = Adafruit_VL6180X();

const int numReadings = 200;
const int stepsPerRevolution = 2100;  // change this to fit the number of steps per revolution for your motor

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

// initialize the stepper library:
Stepper myStepper(stepsPerRevolution, 48, 50, 49, 51);

void setup()
{
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 4);
  // Print a message to the LCD.
  lcd.print("Distance");

  {
    // set the speed at 60 rpm:
    myStepper.setSpeed(7);
  }
  Serial.begin(115200);
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  // wait for serial port to open on native usb devices
  while (!Serial) {
    delay(1);
  }

  Serial.println("Adafruit VL6180x test!");
  if (! vl.begin()) {
    Serial.println("Failed to find sensor");
    while (1);
  }
  Serial.println("Sensor found!");
}

void loop( ) {
  uint8_t range = vl.readRange();
  uint8_t status = vl.readRangeStatus();

  if (status == VL6180X_ERROR_NONE) {
    // subtract the last reading:
    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] =  uint8_t (range);
    // add the reading to the total:
    total = total + readings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;

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

    // calculate the average
    average = total / numReadings;
    // send it to the computer as ASCII digits

    int result;

    result = (average - 20); //sensor offset

    lcd.setCursor(0, 1);
    lcd.print("          ");
    lcd.setCursor(0, 1);
    lcd.print(result);
    lcd.print("mm");

    Serial.print("Range: ");  Serial.println(result);
    delay(10);        // delay in between reads for stability
  }
  if (result > 0) {
    myStepper.step(-stepsPerRevolution);
  }
//  if (result < 0) {
//    myStepper.step(stepsPerRevolution);
//  }


}

void down()
{
  // step one revolution  in one direction:
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);
  delay(500);
}

void up()
{
  // step one revolution in the other direction:
  Serial.println("counterclockwise");
  myStepper.step(-stepsPerRevolution);
  delay(500);

}

Errr...the second if and the code which might have changed the step direction is commented out.

Also you have functions up() and down() that are never used.

Do you see the correct value for "result" on the Serial monitor?

Steve

slipstick:
Errr...the second if and the code which might have changed the step direction is commented out.

Also you have functions up() and down() that are never used.

Do you see the correct value for "result" on the Serial monitor?

Steve

Sorry the commenting out was my experimenting trying to figure out what was happening.
With both "If's" active the serial monitor doesnt change, it only shows the offset amount.
With the "If's" commented out the serial monitor and the LCD show the result as expected.

The Up and Down functions again were my experimenting, I tried setting them as Void's and calling them from the "If" statements but still no good.

readings[readIndex] =  uint8_t (range);

Should be:

readings[readIndex] =  range;

Why so many samples to average? It will take a long time for changes to filter through.
How is your motor connected to Mega? Not wired directly I hope.
That motor will have a multiple of 513 steps per rev, with your setup (half stepping I think) it will probably be 1026.

A light comes on…just possibly.

Shouldn’t you only be calculating the average and result and trying to move the stepper when you have completed the set of readings i.e. when you set readIndex back to 0. So all that stuff should be inside the “if we’re at the end of the array” group.

Try this (completely untested):

// include the library code:
#include <Wire.h>
#include "Adafruit_VL6180X.h"
#include <Stepper.h>
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

Adafruit_VL6180X vl = Adafruit_VL6180X();

const int numReadings = 200;
const int stepsPerRevolution = 2100;  // change this to fit the number of steps per revolution for your motor

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

// initialize the stepper library:
Stepper myStepper(stepsPerRevolution, 48, 50, 49, 51);

void setup()
{
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 4);
  // Print a message to the LCD.
  lcd.print("Distance");

  {
    // set the speed at 60 rpm:
    myStepper.setSpeed(7);
  }
  Serial.begin(115200);
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  // wait for serial port to open on native usb devices
  while (!Serial) {
    delay(1);
  }

  Serial.println("Adafruit VL6180x test!");
  if (! vl.begin()) {
    Serial.println("Failed to find sensor");
    while (1);
  }
  Serial.println("Sensor found!");
}

void loop( ) {
  uint8_t range = vl.readRange();
  uint8_t status = vl.readRangeStatus();

  if (status == VL6180X_ERROR_NONE) {
    // subtract the last reading:
    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] =  uint8_t (range);
    // add the reading to the total:
    total = total + readings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;
    delay(10);        // delay in between reads for stability
    
    // if we're at the end of the array...
    if (readIndex >= numReadings)
    {
      // ...wrap around to the beginning:
      readIndex = 0;


      // calculate the average
      average = total / numReadings;
      // send it to the computer as ASCII digits

      int result;

      result = (average - 20); //sensor offset

      lcd.setCursor(0, 1);
      lcd.print("          ");
      lcd.setCursor(0, 1);
      lcd.print(result);
      lcd.print("mm");

      Serial.print("Range: ");  Serial.println(result);

      if (result > 0) {
        myStepper.step(-stepsPerRevolution);
      }
      if (result < 0) {
        myStepper.step(stepsPerRevolution);
      }
    }
  }
}

Thank you Slip, that works nicely.
I'm just adjusting the number of steps etc to make it a bit smoother but that was exactly what I was after.
Next onto my water flow and temp alarm functions, I might well be back.....