Function not Looping issues

Need help troubleshooting a sketch. The idea is you press a button it goes to the corresponding program loops until level then returns to the button. The problem is I can't get it to loop and I don't know where I'm going wrong. It'll only run through once.

 void leveling() {
    mpu.update();

  if ((millis() - timer) > 10) {  // print data every 10ms
    Serial.println("X : ");
    Serial.println(mpu.getAngleX());
    if (mpu.getAngleX() < -1 & mpu.getAngleX() > -15) digitalWrite(11, LOW);
    else {
      digitalWrite(11, HIGH);
    }
    if (mpu.getAngleX() > 1 & mpu.getAngleX() < 15) {
      digitalWrite(7, LOW);
    } else {
      digitalWrite(7, HIGH);
    }
    if (mpu.getAngleX() < 1 & mpu.getAngleX() > -1) digitalWrite(10, HIGH);
    else {
      digitalWrite(10, LOW);
    }
    timer = millis();
  }
    return;
  }

&& for logical AND, not &

made that adjustment still only going through once

OK. Post your code again to show the changes.

You have some gaps. If , for example, mpu.getAngleX() is exactly equal to 1 it falls through or if >= 15.

How is function leveling() being called ? in a loop ? Show the code where it is called.

What is the data type of timer . It should be uint32_t.

What datatype does this return ?

This is the full Sketch. its still only going through once. i probably have a fundamental issue somewhere

//RV auto leeveling program
//designed to run linear actuators to help leveling process


#include "Wire.h"
#include <MPU6050_light.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte ROWS = 1;  //1 rows
const byte COLS = 4;  //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },

};
byte rowPins[ROWS] = { 9 };     //connect to the row pinouts of the keypad
byte colPins[COLS] = { 5, 4 };  //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
MPU6050 mpu(Wire);
unsigned long timer = 0;


int i = 0;

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  pinMode(10, OUTPUT);  //led
  //digitalWrite(10, LOW);
  pinMode(11, OUTPUT);  //Relay module 1
  digitalWrite(11, HIGH);
  pinMode(12, OUTPUT);
  digitalWrite(12, HIGH);  //Relay module 1
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);  //Relay module 2
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);  //Relay module 2
  Serial.begin(9600);
  lcd.init();
  lcd.setBacklight(HIGH);
  Wire.begin();

  customKeypad.addEventListener(keypadEvent);  // Add an event listener for this keypad
  byte status = mpu.begin();
  lcd.setCursor(0, 0);
  lcd.print(F("MPU6050 status: "));
  lcd.setCursor(0, 1);
  lcd.print(status);
  while (status != 0) {}  // stop everything if could not connect to MPU6050
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Calculating offsets,"));
  lcd.setCursor(0, 1);
  lcd.println("Do not move MPU6050");
  // mpu.upsideDownMounting = true; // uncomment this line if the MPU6050 is mounted upside-down
  mpu.calcOffsets();  // gyro and accelero
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.println("Done!\n");
  delay(1000);
  lcd.clear();
}
void loop() {
  int pitch = mpu.getAngleX();
  char customKey = customKeypad.getKey();  //converts character to integer
  mpu.update();
  lcd.setCursor(0, 0);
  lcd.print("1: Auto 2: RESET");
  lcd.setCursor(0, 1);
  lcd.print("Pitch:");
  lcd.print(mpu.getAngleX());
  if (customKey) {  // Waiting for button press from keypad
    Serial.println(customKey);
    Serial.println(pitch);
  }
}

void keypadEvent(KeypadEvent customKey) {
  switch (customKeypad.getState()) {
    case HOLD:
      if (customKey == '2') {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Packing Up");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("returning motors to up postion");
        digitalWrite(12, LOW);
        digitalWrite(8, LOW);
        delay(15000);
        digitalWrite(12, HIGH);
        digitalWrite(8, HIGH);
        lcd.setCursor(0, 0);
        lcd.print("Motors returned to up position");
        delay(2000);
      }
      break;
    case PRESSED:
      if (customKey == '1') {
        int pitch = mpu.getAngleX();
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Auto run");
        delay(3000);
        lcd.clear();

        leveling();

        delay(10000);
        digitalWrite(10, LOW);
        lcd.clear();

        lcd.setCursor(0, 0);
        lcd.print("Auto run Complete");
        lcd.setCursor(0, 1);
        lcd.print("System Level");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Current Angle");
        lcd.setCursor(0, 1);
        lcd.print(mpu.getAngleX());
        delay(10000);
        lcd.clear();
      }
      break;
  }
}
void leveling() {  //runs relay module. this activates linear actuators to level trailer
  mpu.update();

  if ((millis() - timer) > 10) {  // print data every 10ms
    Serial.println("X : ");
    Serial.println(mpu.getAngleX());
    
    if (mpu.getAngleX() < -1 && mpu.getAngleX() > -15) digitalWrite(11, HIGH);  //parameters for out of level 15 degree max limit for 20ft trailer
    else {
      digitalWrite(11, HIGH);
    }
    if (mpu.getAngleX() > 1 && mpu.getAngleX() < 15) {  //parameters for out of level 15 degree max limit for 20ft trailer
      digitalWrite(7, HIGH);
    } else {
      digitalWrite(7, HIGH);
    }
    if (mpu.getAngleX() < 1 && mpu.getAngleX() > -1) digitalWrite(10, HIGH);  //parameters for being within level
    else {
      digitalWrite(10, HIGH);
    }
    timer = millis();
  }
  else {
    leveling();
  }

}

did you fix all cases or just that one?

all cases were fixed

potential for infinite recursion

i threw that in to try and force it to loop still wouldnt

You are now calling function leveling() recursively. That may get stuck somewhere.

i can put that line of code in or out and it doesnt change

You are triggering leveling() only once on a button press.
You should, on the button press, set a global status variable. Leveling() should then be called in the loop when/while the status variable is set. The status variable can be unset when it is determined that the device is once again level.

You lost me a little bit. Can you give me an example or more detail?

roughly like this . . .

. . .
bool correctLevel = false ;  // global (read as level to be corrected)
. . .

void loop() {
. . .
if ( correctLevel == true ) leveling();
. . .
}


  
void keypadEvent(KeypadEvent customKey) {
. . .
    case PRESSED:
      if (customKey == '1') {
        int pitch = mpu.getAngleX();
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Auto run");
        delay(3000);
        lcd.clear();

        //leveling();
        correctLevel = true ; // new

        delay(10000);
. . .
}


void leveling() {
 . . .
 as before but . . .
 if ( <device now level> ) correctLevel = false ;   // you have to dermine that it is level somehow
 . . .
}

No good. still running right past the loop

Ok. Show your code with the latest amendments.

A different approach was found to get it to run. Thank you for your help though.
a while loop was used at the beginning of leveling()

void leveling() {     //runs relay module. this activates linear actuators to level trailer
  while (true) {
    mpu.update();
    if ((millis() - timer) > 10) {
      Serial.println("X : ");
      Serial.println(mpu.getAngleX());
      if (mpu.getAngleX() < -1 & mpu.getAngleX() > -15) {         //parameters for out of level 15 degree max limit for 20ft traile
        digitalWrite(11, LOW);
      } else {
        digitalWrite(11, HIGH);
      }

      if (mpu.getAngleX() > 1 && mpu.getAngleX() < 15) {          //parameters for out of level 15 degree max limit for 20ft traile
        digitalWrite(7, LOW);
      } else {
        digitalWrite(7, HIGH);
      }

      if (mpu.getAngleX() < 1 && mpu.getAngleX() > -1) {          //parameters for LED = Indicates Level+ 
        digitalWrite(10, HIGH);
        return;
      } else {
        digitalWrite(10, LOW);
      }

      timer = millis();
    }
  }
}

That looks like a good solution but it will block other avtivities during a leveling operation. I now see what your stopping condition is -1 < mpu.getAngleX() < 1. Also putting the repeated calls of leveling() in the loop(), as I suggested, would not have worked correctly because of the delay() statements in keypadEvent() before dropping into the loop().

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