Push Button State Change (Multiple Conditions)

Hello,

I'm trying to implement another conditional state change to the below code. I need the code to check if pin4 is high first. If it is, serial print "MACHINE_ON" and continue with the (push button) code until the state of pin 4 changes. If pin 4 changes, serial print "MACHINE_OFF".

The output in the serial monitor should look like this-

MACHINE_ON
LED ON
LED OFF
LED ON
LED OFF
LED ON
LED OFF
MACHINE_OFF
MACHINE_ON
LED ON
LED OFF
MACHINE_OFF
etc...

I tried changing the code myself but I made a mess of it. Any and all help would be greatly appreciated!


const int buttonPin = 3;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;        // the current state of the output pin
int buttonState;            // the current reading from the input pin
int lastButtonState = LOW;  // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() 
{
  Serial.begin(9600);

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

   // set initial LED state
  digitalWrite(ledPin, ledState);
}

 void loop() 
{
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

   // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) 
  {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 

   if ((millis() - lastDebounceTime) > debounceDelay) 
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) 
    {
      buttonState = reading;
      ledState = !ledState;
      digitalWrite(ledPin, ledState);
     
      if (buttonState == HIGH) 
      {
        Serial.println("LED ON");
      }
      else
      {
        Serial.println("LED OFF");
      }
    }
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

It seems like the posted code is something you have copied from somewhere and now you want strangers to spend time on adding features to it, aye? Try to add your own code for pin 4 first..

1 Like

Post your mess and we will help sort it out.

@blh64 I appreciate the sincere response. Here's the updated code aka my attempt (it won't even compile)-


const int buttonPin = 3;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

const int powerPin = 4;    // the number of the input power pin

// Variables will change:
int ledState = HIGH;        // the current state of the output pin
int buttonState;            // the current reading from the input pin
int lastButtonState = LOW;  // the previous reading from the input pin

int machineState;           // current reading from the power pin
int lastmachineState;       // previous readin from the power pin


// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
unsigned long debounceDelay1 = 50;    // the debounce time; increase if the output flickers


void setup() 
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop() 
{
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  int mreading = digitalRead(powerPin);
  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  
  // If the switch changed, due to noise or pressing:
  
  
  if (mreading != lastmachineState)
  {
      lastDebounceTime1 = millis();
  }


  if ((millis() - lastDebounceTime1) > debounceDelay1) 
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    // if the button state has changed:

    if (mreading != machineState)
   {
    machineState = reading;
    if (machineState == HIGH)
    {
      Serial.println("MACHINE ON")
   
    if (reading != lastButtonState) 
  {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 

 

  if ((millis() - lastDebounceTime) > debounceDelay) 
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    
    
    if (reading != buttonState) 
    {
      buttonState = reading;
      ledState = !ledState;
      digitalWrite(ledPin, ledState);
     
      if (buttonState == HIGH) 
      {
        Serial.println("LED ON");
      }
      else
      {
        Serial.println("LED OFF");
      }
    }
    else
    Serial.println("MACHINE OFF")
}
}
}
}
}
  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

Here's what I thought would work, but I can imagine it serial printing this-

MACHINE ON
LED ON
MACHINE ON
LED OFF
MACHINE ON
LED ON...

and I don't want that.

It is always good to post your error message as well so people can more easily help.

sketch_sep21a:64:5: error: expected ';' before 'if'
     if (reading != lastButtonState)
     ^~
sketch_sep21a:95:1: error: expected ';' before '}' token
 }
 ^
C:\Users\brianh\AppData\Local\Temp\arduino_modified_sketch_322256\sketch_sep21a.ino: At global scope:
sketch_sep21a:102:3: error: 'lastButtonState' does not name a type
   lastButtonState = reading;
   ^~~~~~~~~~~~~~~
sketch_sep21a:103:1: error: expected declaration before '}' token
 }
 ^
exit status 1
expected ';' before 'if'

That is telling you that you probably forgot to terminate the previous line with a semicolon. and...

      Serial.println("MACHINE ON")

sure enough, there is no semi-colon at the end of that line (and another one as well)

If you also take the time to auto format your code (CTL-T) then you will notice that you don't have a balanced pair of {}

const int buttonPin = 3;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

const int powerPin = 4;    // the number of the input power pin

// Variables will change:
int ledState = HIGH;        // the current state of the output pin
int buttonState;            // the current reading from the input pin
int lastButtonState = LOW;  // the previous reading from the input pin

int machineState;           // current reading from the power pin
int lastmachineState;       // previous readin from the power pin


// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
unsigned long debounceDelay1 = 50;    // the debounce time; increase if the output flickers


void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop()
{
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  int mreading = digitalRead(powerPin);
  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:
  // If the switch changed, due to noise or pressing:


  if (mreading != lastmachineState)
  {
    lastDebounceTime1 = millis();
  }


  if ((millis() - lastDebounceTime1) > debounceDelay1)
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    // if the button state has changed:

    if (mreading != machineState)
    {
      machineState = reading;
      if (machineState == HIGH)
      {
        Serial.println("MACHINE ON");

        if (reading != lastButtonState)
        {
          // reset the debouncing timer
          lastDebounceTime = millis();
        }



        if ((millis() - lastDebounceTime) > debounceDelay)
        {
          // whatever the reading is at, it's been there for longer
          // than the debounce delay, so take it as the actual current state:


          if (reading != buttonState)
          {
            buttonState = reading;
            ledState = !ledState;
            digitalWrite(ledPin, ledState);

            if (buttonState == HIGH)
            {
              Serial.println("LED ON");
            }
            else
            {
              Serial.println("LED OFF");
            }
          }
          else
          {
            Serial.println("MACHINE OFF");
          }
        }
      }
    }

    // save the reading.  Next time through the loop,
    // it'll be the lastButtonState:
    lastButtonState = reading;
  }
}

Thank you for the automatic formatting trick! I didn't even know that existed. Also, thank you for pointing out both of my syntax errors. I still don't think the code is structured properly. I don't get any serial print "Machine on" when Pin4 receives power. Any insight? Thanks

if mreading is not the same as lastmachineState then you reset your debounce time so your very next if() statement will never be true AND you never update lastmachineState

You should also break those two conditions apart. Check your machine on/off first, if it has changed, print your message.

If it is currently off, you can just return from loop() which skips the reset of loop() and goes back to the beginning. No need to worry about the LED if the machine is OFF.

Hello
Who is guiding the a.m. state changes?

if mreading is not the same as lastmachineState then you reset your debounce time so your very next if() statement will never be true AND you never update lastmachineState

Sorry, that doesn't make any sense. If you refer to my first post, the code I used to start with, it starts that same way. I just created a second set of variables that mirror those original variables.

You should also break those two conditions apart. Check your machine on/off first, if it has changed, print your message.

If it is currently off, you can just return from loop() which skips the reset of loop() and goes back to the beginning. No need to worry about the LED if the machine is OFF.

That's what I assumed would be the correct course of action. I don't know how to structure it. I need to be shown what it looks like in order to understand it.

const int buttonPin = 3;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

const int powerPin = 4;    // the number of the input power pin

// Variables will change:
int ledState = HIGH;        // the current state of the output pin
int buttonState;            // the current reading from the input pin
int lastButtonState = LOW;  // the previous reading from the input pin

int machineState;           // current reading from the power pin
int lastmachineState;       // previous readin from the power pin


// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
unsigned long debounceDelay1 = 50;    // the debounce time; increase if the output flickers


void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop()
{
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  int mreading = digitalRead(powerPin);
  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:
  // If the switch changed, due to noise or pressing:


  if (mreading != lastmachineState) {
    lastDebounceTime1 = millis();
  }

  if ((millis() - lastDebounceTime1) > debounceDelay1) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    if ( mreading != machineState ) {
      machineState = mreading;
      if (machineState == HIGH) {
        Serial.println("MACHINE ON");
      }
      else {
        Serial.println("MACHINE OFF");
      }
    }
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastmachineState = machineState;

  if ( lastmachineState == LOW ) {
    return; // nothing more to do if machine is OFF
  }

  if (buttonState != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    if (reading != buttonState) {
      buttonState = reading;
      ledState = !ledState;
      digitalWrite(ledPin, ledState);

      if (buttonState == HIGH) {
        Serial.println("LED ON");
      }
      else {
        Serial.println("LED OFF");
      }
    }
  }
  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

I tried your code and my serial monitor stays completely blank. No machine on or off when power is applied to pin 4. Is this because the way you wrote it looks for (2) conditions to be true for it to say "machine on"? or is the second debounce if statement holding it up?

Okay, took a quick visit to https://wokwi.com

const int buttonPin = 3;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

const int powerPin = 4;    // the number of the input power pin

// Variables will change:
int ledState = HIGH;        // the current state of the output pin
int buttonState;            // the current reading from the input pin
int lastButtonState = LOW;  // the previous reading from the input pin

int machineState;           // current reading from the power pin
int lastmachineState;       // previous readin from the power pin


// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
unsigned long debounceDelay1 = 50;    // the debounce time; increase if the output flickers

byte pushCount = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
  Serial.println("Ready");
}

void loop()
{
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  int mreading = digitalRead(powerPin);
  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:
  // If the switch changed, due to noise or pressing:


  if (mreading != lastmachineState) {
    lastDebounceTime1 = millis();
  }

  if ((millis() - lastDebounceTime1) > debounceDelay1) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    if ( mreading != machineState ) {
      machineState = mreading;
      if (machineState == HIGH) {
        Serial.println("MACHINE ON");
      }
      else {
        Serial.println("MACHINE OFF");
      }
    }
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastmachineState = mreading;

  if ( lastmachineState == LOW ) {
    return; // nothing more to do if machine is OFF
  }

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    if (reading != buttonState) {
      buttonState = reading;
      if ( buttonState == LOW) {
        ledState = !ledState;
        digitalWrite(ledPin, ledState);
        if (ledState) {
          Serial.println("LED ON");
        }
        else {
          Serial.println("LED OFF");
        }
      }
    }
  }
  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

Okay, that worked beautifully - thank you so much! Now that I've tested it quite a few times... I think I'm going to have to tweak it even further. The button press isn't tied to a physical button, it's a laser signal, and I'm monitoring when it turns on and off. I'm saving the On/Off messages to a database and it's going to balloon the storage size pretty quickly. I think the better way to do it is to count how long the laser is on in one minute intervals. I still need this script to run (so it wasn't a waste of time) I just won't be logging the data it outputs, it will be displayed in real-time.

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