how to run part of void loop only once depending on button push

I would appreciate some help in finding the answer to this problem. I am building a handheld pushbutton remote control to turn a sonoff basic switch on and off. One push on and one push off. The code I have put together performs the toggle function with the pushbutton just fine as long as the only indicator is the LED. However, the "client.publish" statement running constantly with the loop is putting MQTT into orbit!!! My MQTT server is running on a RPi on my local wifi. It is imperative that this operation take place in "house". My NodeRed debug system shows the correct message being sent but there are hundreds of them. And the message does change when the button is pushed, it just takes a long time to see them. I appreciate any and all advise. The last section of the code is here.

pinMode(BUTTON, INPUT); // push button 
 pinMode(LED, OUTPUT); // anything you want to control using a switch e.g. a Led
}
void loop () {
 switchState = digitalRead(BUTTON); // read the pushButton State
 if (switchState != oldSwitchState) // catch change
 {
 oldSwitchState = switchState;
 if (switchState == HIGH)
 {
 // toggle
 lightsOn = !lightsOn;
 }
 }
 if(lightsOn)
 {
 digitalWrite(LED, HIGH); // set the LED on
 client.publish("home/office/sonoff1", "on");
 } else {
 digitalWrite(LED, LOW); // set the LED off
 client.publish("home/office/sonoff1", "off");
 }
}

Thanks for looking Kentm

Can you just move the check into the switch detect logic?

void loop () 
{
    switchState = digitalRead(BUTTON); // read the pushButton State
    if (switchState != oldSwitchState) // catch change
    {
        oldSwitchState = switchState;
        if (switchState == HIGH)
        {
            // toggle
            lightsOn = !lightsOn;
        }
        
        if(lightsOn)
        {
            digitalWrite(LED, HIGH); // set the LED on
            client.publish("home/office/sonoff1", "on");
        } 
        else 
        {
            digitalWrite(LED, LOW); // set the LED off
            client.publish("home/office/sonoff1", "off");
        }
    }
    
}

we used flags to note a state.

and we use if() statements.

if the flag light showing the is off
and if the button is pressed

  • then turn the light on and change the flag to show the light is on

as you can see, you cannot get past the first if() if the light is already on and then you cannot get past the next unless the button is pressed.

so, only when the light is off and the button is pressed, can you get to the next step.

Thanks to "BLACKFIN" and "dave-in-nj". I have re-read your replies several times and it appears to me as if my original code is already as you are describing. Besides being old and grumpy, I guess I have been working on this project so long that I should set it aside for awhile. Maybe I did not make my issue clear here. The issue is only with the "client.publish" statements. The LED responds as expected. My assumption is that the RPi is going into "gridlock" with the messages coming at it so fast. It responds with the correct message after a button push but it takes awhile to see it. The sonoff switch just goes dead and I have to power down the RPi to reset everything. I have two of those switches connected and the both respond perfectly to the NodeRed dashboard. But when I run this sketch, the one I am currently publishing to goes dead.

Thanks again Kentm

merkelck:
Thanks to “BLACKFIN” and “dave-in-nj”. I have re-read your replies several times and it appears to me as if my original code is already as you are describing.

No, it’s not. In your code, the section in loop():

    if(lightsOn)
    {
        digitalWrite(LED, HIGH); // set the LED on
        client.publish("home/office/sonoff1", "on");
    }
    else 
    {
        digitalWrite(LED, LOW); // set the LED off
        client.publish("home/office/sonoff1", "off");
    }

runs every single loop. You’re machine-gunning client.publish() calls as fast as the Arduino is running its loop.

Look closely at my modification to your code. It sends the message only on the change of state of the switch.

Did you try it?

Blackfin extended the last bracket to so that the publish was inside of the if()

pinMode(BUTTON, INPUT); // push button
pinMode(LED, OUTPUT); // anything you want to control using a switch e.g. a Led
}
void loop () {
  switchState = digitalRead(BUTTON); // read the pushButton State
  if (switchState != oldSwitchState) // catch change
    {
      oldSwitchState = switchState;
     if (switchState == HIGH)
       {
        // toggle
        lightsOn = !lightsOn;
       }
     } // +++++++++++++++++++ end of if ( switchState != ....
       // move this bracket to the end

     // ++++++++++++++++++ new if() statement - runs every loops = problem
  if (lightsOn)
  {
    digitalWrite(LED, HIGH); // set the LED on
    client.publish("home/office/sonoff1", "on");
  } else {
    digitalWrite(LED, LOW); // set the LED off
    client.publish("home/office/sonoff1", "off");
  }
}

Thank you both. My tired old eyes finally caught the wild }. I took up this arduino stuff to give something to do in retirement and it keeps me going. I am using these devices to replace an old X10 home automation system that I have had running since back in the '80s. Thanks again. Now I can press on . One problem at a time.... Kentm

merkelck: Thank you both. My tired old eyes finally caught the wild }. I took up this arduino stuff to give something to do in retirement and it keeps me going. I am using these devices to replace an old X10 home automation system that I have had running since back in the '80s. Thanks again. Now I can press on . One problem at a time.... Kentm

Nice. Good luck with the project.