LongPress works intermittent

I've been working on a project to automatically level my food trailer for a month now. This has been my only experience with coding and the Arduino. I'm very well versed in automotive DC wiring so I had a little head start there.

I'm using 4 electric tongue jacks that I modified and welded to each corner of the trailer. I'm using an Arduino Uno to control them. I'm using a toy Ambulance with a breadboard taped to the top of it, containing LEDs and a Joystick. the LEDs take the place of the actual jacks in my proof of concept/trial and error machine.

I have have the majority of the program written and ready to go for my first iteration of the system. Some things will be manual, but for the most part its automatic.

The last piece of the program for this first iteration is being able to long press the joystick (3 seconds) to write "corrected" values to the EEPROM, and an even longer press of the joystick (6 seconds) to write those values to 0, resetting the system to "factory settings"
Basically this will let me tell the controller that I have found a new "Level" that I want it to adjust to each time it executes.

Below is the sketch for that to happen, without the EEPROM writes included. Instead, it should return an ascending counter in the serial monitor to show its working.... or if it's not.
I don't see the problem, mainly because the outcomes are intermittent, with no rhyme or reason as to why. (at least that I can tell.)

int NewLevelTime = 3000;
int ResetLevelToZeroTime = 6500;
int JoyPinCurrentState = HIGH;
int JoyPinPreviousState = HIGH;
unsigned long NewLevelPress = 0;
unsigned long ResetLevelToZeroPress = 0;
int debounceDelay = 50;
int JoyPin;

int New = 0;
int Zero = 0;



void setup() {
  Serial.begin(9600);
  pinMode(0, INPUT_PULLUP);
}

void loop() {
  Serial.print("New Level Value Saves=");
  Serial.print(New);
  Serial.print(" ");
  Serial.print("Factory Value Saves=");
  Serial.println(Zero);
  JoyPinCurrentState = digitalRead(JoyPin);


  if (JoyPinCurrentState == LOW && JoyPinPreviousState == HIGH) {
    NewLevelPress = millis();
    ResetLevelToZeroPress = millis();
    JoyPinPreviousState = JoyPinCurrentState;
  } else if (JoyPinCurrentState == HIGH && JoyPinPreviousState == LOW) {
    JoyPinPreviousState = JoyPinCurrentState;
  }
  if (JoyPinCurrentState == LOW) {
    //Debounce the button
    if ((millis() - NewLevelPress) > debounceDelay) {
      //long press of JoyPin will set a new "Level" for the AutoLevel Function by
      //writing new values for AcXoff,AcYoff,AcZoff into the EEPROM
      if ((millis() - NewLevelPress) == NewLevelTime) {  //5 Seconds
        //Write new value for FrontBackOff into the EEPROM
        //Serial.println("Write New Level Value");
        New++;
      }
      if ((millis() - ResetLevelToZeroPress) == ResetLevelToZeroTime) {  //10 Seconds
        //Write 0 values for AcXoff,AcYoff,AcZoff into the EEPROM
        //Serial.println("Write Level Values to 0");
        Zero++;
      }
    }
  }
}

Thanks in advance for the help with this, I appreciate all the answers I have already found on here!

Your Arduino Uno uses pins 0 and 1 for the Serial you just initialized. You cannot use pins 0 and 1 for stuff that is already in use for other things.

No pin at all?

Are you trying to redefine mathematics here? Try to make variable names that don't create confusion. If it's like "zero the scale", perhaps "ZeroOffset", "ZeroCalibration" or something like that?

I suggest backing up and tackling a few tutorials and examples, perhaps make some easier projects of your own. Unless this project is a one-off and you don't care to continue programming much after this...

You seem to have almost mastered C syntax but your design skill is weak. You can get that with experience.

Just in passing,

if ((millis() - NewLevelPress) == NewLevelTime)

does not need parenthesis, subtraction beats comparison in the order of operations:

if (millis() - NewLevelPress == NewLevelTime)

but this leaves open the possibility that the value might overtake equality before the program reaches this line. You should make it fail safe with

if (millis() - NewLevelPress >= NewLevelTime)

or find some other way to do whatever you are up to here.

Your Arduino Uno uses pins 0 and 1 for the Serial you just initialized. You cannot use pins 0 and 1 for stuff that is already in use for other things.

Thanks!
I thought this was only on the TX pin, as there is nothing being received during this program?

When you call the begin() method of Serial on the UART on pins 0,1 it initializes processor hardware that overrides the normal I/O functionality of both of those pins.

@anon57585045

Are you trying to redefine mathematics here? Try to make variable names that don't create confusion. If it's like "zero the scale", perhaps "ZeroOffset", "ZeroCalibration" or something like that?

I suggest backing up and tackling a few tutorials and examples, perhaps make some easier projects of your own. Unless this project is a one-off and you don't care to continue programming much after this...

You seem to have almost mastered C syntax but your design skill is weak. You can get that with experience.

Thanks for the help! I have been trial and erroring this over and over and am happy to know some of what I'm doing is correct. :slight_smile:

I have listened to, watched, and read a bunch of tutorial to get me this far. I'm not sure doing something smaller or different will help me, as I learn by doing what's on my mind.
I think I'm at the point of "WHY" these things happen/don't happen, and just need a little insight from others to get me pointed in the right direction.

@anon57585045

Just in passing,

if ((millis() - NewLevelPress) == NewLevelTime)

does not need parenthesis, subtraction beats comparison in the order of operations:

if (millis() - NewLevelPress == NewLevelTime)

but this leaves open the possibility that the value might overtake equality before the program reaches this line. You should make it fail safe with

if (millis() - NewLevelPress >= NewLevelTime)

or find some other way to do whatever you are up to here.

I had wondered if that was the problem, it was just passing the == before the program reached it, but I assumed the program ran fast enough, being so simple and 0 delays, that wouldn't be the case. But you're suggesting it very well might be! Good to know that my assumption was incorrect.
On the same topic, If I were to use ">=" wouldn't it continue to be true from the 3 second mark and beyond, which would execute the if statement over and over until I released the button? This assumption is why I decided to stay with "==".
I just tried it with ">=" and my assumption is correct.
That being said, my mind thinks there should be a way to say, "hey fella, you got your save, now quit counting!" and the way I would do that is with While statements. Is that the best practice?

Below is the updated sketch, defining a pin for "JoyPin"(10), and changing "Zero" to "Factory",

int NewLevelTime = 3000;
int ResetLevelToZeroTime = 6500;
int JoyPinCurrentState = HIGH;
int JoyPinPreviousState = HIGH;
unsigned long NewLevelPress = 0;
unsigned long ResetLevelToZeroPress = 0;
int debounceDelay = 50;
int JoyPin;

int New = 0;
int Factory = 0;

#define JoyPin 10

void setup() {
  Serial.begin(9600);
  pinMode(10, INPUT_PULLUP);
}

void loop() {
  Serial.print("New Level Value Saves=");
  Serial.print(New);
  Serial.print(" ");
  Serial.print("Factory Value Saves=");
  Serial.println(Factory);
  JoyPinCurrentState = digitalRead(JoyPin);


  if (JoyPinCurrentState == LOW && JoyPinPreviousState == HIGH) {
    NewLevelPress = millis();
    ResetLevelToZeroPress = millis();
    JoyPinPreviousState = JoyPinCurrentState;
  } else if (JoyPinCurrentState == HIGH && JoyPinPreviousState == LOW) {
    JoyPinPreviousState = JoyPinCurrentState;
  }
  if (JoyPinCurrentState == LOW) {
    //Debounce the button
    if ((millis() - NewLevelPress) > debounceDelay) {
      //long press of JoyPin will set a new "Level" for the AutoLevel Function by
      //writing new values for FrontBack and LeftRight into the EEPROM
      if ((millis() - NewLevelPress) >= NewLevelTime) {  //5 Seconds
        //Write new value for FrontBackOff into the EEPROM
        //Serial.println("Write New Level Value");
        New++;
      }
      if ((millis() - ResetLevelToZeroPress) >= ResetLevelToZeroTime) {  //10 Seconds
        //Write 0 values for FrontBack and LeftRight into the EEPROM
        //Serial.println("Write Level Values to 0");
        Factory++;
      }
    }
  }
}

That is why I said, "...or find some other way", I had a feeling. But I don't have time to really study all of your logic in detail. It would have to do with how you have nested the time checks.

I have found another way, using "while" statements. My question is- is it anywhere close to the way it "Should" be done? if not, any suggestions to get me pointed int the correct direction? :slight_smile:

Below is the sketch. I used pin 0 again, and it works as it should. I did this because in my full project, it's one of the only two pins left, and I want to verify if it will work or not. I have read it both ways on this forum-CAN'T use 0/1 if using serial data, or you CAN use pin 0 ONLY if not Receiving any info over serial data. It appears to work just as any of the other I/O pins would. Does anyone have any more info on this? i.e., Is it just frowned upon because it COULD cause problems, but if this is understood, there is nothing wrong with it?

int NewLevelTime = 3000;
int ResetLevelToZeroTime = 6500;
int JoyPinCurrentState = HIGH;
int JoyPinPreviousState = HIGH;
unsigned long NewLevelPress = 0;
unsigned long FactorySettingsPress = 0;
int debounceDelay = 50;
int JoyPin;
int FrontBackOff = 0;
int LeftRightOff = 0;
bool NewLevelBool = false;
bool ResetLevelBool = false;

int NewLevelCounter = 0;
int FactorySettingsCounter = 0;

#define JoyPin 0

void setup() {
  Serial.begin(9600);
  pinMode(10, INPUT_PULLUP);
}

void loop() {
  Serial.print("NewLevelCounter=");
  Serial.print(NewLevelCounter);
  Serial.print(" ");
  Serial.print("FactorySettingsCounter=");
  Serial.println(FactorySettingsCounter);
  JoyPinCurrentState = digitalRead(JoyPin);

  if (JoyPinCurrentState == LOW && JoyPinPreviousState == HIGH) {
    NewLevelPress = millis();
    FactorySettingsPress = millis();
    JoyPinPreviousState = JoyPinCurrentState;
  } else if (JoyPinCurrentState == HIGH && JoyPinPreviousState == LOW) {
    JoyPinPreviousState = JoyPinCurrentState;
  }
  if (JoyPinCurrentState == LOW) {
    //Debounce the button
    if ((millis() - NewLevelPress) > debounceDelay) {
      //long press of JoyPin will set a new "Level" for the AutoLevel Function by
      //writing new values for LeftRight and FrontBack into the EEPROM
      if ((millis() - NewLevelPress) >= NewLevelTime) {  //5 Seconds
        //Write new value for LeftRight and FrontBack into the EEPROM
        //Serial.println("Write New Level Value");
        NewLevelCounter++;
        if (NewLevelCounter >= 1) {
          NewLevelBool = true;
          NewLevelCounter = -1000;  //Make the counter a large, negtive number so its highly
                                    //unlikely to hit again while trying to reset values
        }
      }
      if ((millis() - FactorySettingsPress) >= ResetLevelToZeroTime) {  //10 Seconds
        //Write 0 values for LeftRight and FrontBack into the EEPROM
        //Serial.println("Write Level Values to 0");
        FactorySettingsCounter++;
        if (FactorySettingsCounter >= 1) {
          ResetLevelBool = true;
          FactorySettingsCounter = -1000;  //Make the counter a large, negtive number so its highly
                                           //Unlikely to hit again while trying to reset values
        }
      }
    }
  }
  while (NewLevelBool == true) {
    //EEPROM.put(0, FrontBackOffReading);
    //EEPROM.put(10, LeftRightOffReading);
    Serial.println("NewLevelUpated");
    delay(500); //Delay to make it easier to see in Serial Monitor
    NewLevelBool = false; //exit the while loop
  }

  while (ResetLevelBool == true) {
    //EEPROM.put(0, FrontBackOffReading);
    //EEPROM.put(10, LeftRightOffReading);
    Serial.println("FactorySettingsUpdated");
    delay(500); //Delay to make it easier to see in Serial Monitor
    ResetLevelBool = false;//exit the while lool
  }
}

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