Why does my if function keep looping?

Sorry if this has been addressed before, but I can’t find any other thread. I’m building a cosplay prop (lightning gun) and am having issues with an if function in my code. When I pull the trigger (momentary switch), it cues the lightning light. It’s supposed to turn off, then fade on and stay on. However when I pull the trigger, it fades on, then loops the if statement forever.

In looking at the serial monitor, it keeps spitting out alternate 1s and 0s as it works through the if statement over and over. It’s like the program thinks that the trigger is held down (or pulled repeatedly), but it’s not. The digitalRead(trigger) should notice that the value is no longer 0 and not perform the if function, right? Any help would be appreciated.

int lightning = 10;
int trigger = 2;
//int triggerVal = 1;

void setup() {
  Serial.begin(9600);
  pinMode(trigger, INPUT_PULLUP);
  pinMode(lightning, OUTPUT);
}

void loop() {
  int triggerVal = digitalRead(trigger);
  if(triggerVal == 0) {
    Serial.println(triggerVal);     // this shows me the 0 in the serial monitor as the trigger is pulled
    analogWrite(lightning,0);
    for(int fadeValue1 = 0 ; fadeValue1 <= 255; fadeValue1 +=20) {
      analogWrite(lightning,fadeValue1);
      delay(50);
    }
    triggerVal = 1;     // trying to reset the trigger value to "off"
    Serial.println(triggerVal);     // this part shows me the 1 in the serial monitor
  }
}

Then the triggerpin must be reading LOW. Perhaps only due to noise. Try a decent external pullup resistor such as
2.2k, the internal pullup may be too weak.

A branching statement that loops? A non-programming colleague once said that we could solve the problem by adding a "if then loop". The programmers found that expression hilarious and some literally had to leave the room to get their laughter under control.

MarkT:
Then the triggerpin must be reading LOW. Perhaps only due to noise. Try a decent external pullup resistor such as
2.2k, the internal pullup may be too weak.

I wrote a sketch that eliminates everything but the button. It essentially just read the state of the button. With a Serial.println(triggerVal), the serial monitor spits out constant 1s until I hit the trigger, at which point I get a brief stream of 0s before it goes back to 1s. It didn't seem to have any interference there. That leads me to believe it's a programming error, but I may be wrong (as is frequent).

    triggerVal = 1;     // trying to reset the trigger value to "off"
    Serial.println(triggerVal);     // this part shows me the 1 in the serial monitor

Nice try, but moments later code returns to top of loop

void loop() {
  int triggerVal = digitalRead(trigger);

That digitalRead resets triggerVal to 0, and you know what happens.

You need another variable to know if lightning is already active, and if it is, don't do the fade in.

Look at the state change detection example, too. You want the effect to happen when the switch BECOMES pressed, not when the switch IS pressed.

PaulS:
Look at the state change detection example, too. You want the effect to happen when the switch BECOMES pressed, not when the switch IS pressed.

I modified my code to use the state change detection. It reads a steady stream of 1s and when I pull the trigger, it prints 0s (as it should). There are no repeating 1s and 0s like I got with my original code. However now the light doesn’t turn on when the trigger is pulled. I find it odd that Serial.println(triggerVal) in the second “if” block runs appropriately, however the rest of the code in the same “if” block does not.

Gabriel_swe:

    triggerVal = 1;     // trying to reset the trigger value to "off"

Serial.println(triggerVal);     // this part shows me the 1 in the serial monitor





Nice try, but moments later code returns to top of loop


void loop() {
 int triggerVal = digitalRead(trigger);



That digitalRead resets triggerVal to 0, and you know what happens. 

You need another variable to know if lightning is already active, and if it is, don't do the fade in.

Why does it reset to 0? Shouldn’t it just read the state of the button (whether it’s pressed or not)?

I just wish that I knew what I was doing. I’m not very good with this stuff.

Here’s my updated code.

int lightning = 10;
int trigger = 2;

int triggerVal = 0;
int lastTriggerVal = 0;

void setup() {
  Serial.begin(9600);
  pinMode(trigger, INPUT_PULLUP);
  pinMode(lightning, OUTPUT);
}

void loop() {
  triggerVal = digitalRead(trigger);
  Serial.println(triggerVal);
  if (triggerVal != lastTriggerVal) {
    if(triggerVal == 0) {
      Serial.println(triggerVal);     // this shows me the 0 in the serial monitor as the trigger is pulled
      analogWrite(lightning,0);
      for(int fadeValue1 = 0 ; fadeValue1 <= 255; fadeValue1 +=20) {
        analogWrite(lightning,fadeValue1);
        delay(50);
      }
    }
  }
  triggerVal = lastTriggerVal;
}
      Serial.println(triggerVal);     // this shows me the 0 in the serial monitor as the trigger is pulled

How do you KNOW that? Anonymous printing sucks. You have two statements that print triggerVal. You haven't a clue which one printed what value when.

PaulS:

      Serial.println(triggerVal);     // this shows me the 0 in the serial monitor as the trigger is pulled

How do you KNOW that? Anonymous printing sucks. You have two statements that print triggerVal. You haven’t a clue which one printed what value when.

I’m afraid I don’t know what you mean. Sorry for my noob-ness. The first print of triggerVal prints a constant stream of 1s. Then when the trigger is pulled, the second print prints 0s. 0s only appear when the trigger is pulled. However when it starts repeating alternating 1s and 0s, you’re right, I don’t know what causes that and why it starts repeating 0s. What would you recommend?

majhi:
I'm afraid I don't know what you mean. Sorry for my noob-ness. The first print of triggerVal prints a constant stream of 1s. Then when the trigger is pulled, the second print prints 0s. 0s only appear when the trigger is pulled. However when it starts repeating alternating 1s and 0s, you're right, I don't know what causes that and why it starts repeating 0s. What would you recommend?

It means.... if you print something.... under testing conditions..... add extra words...that tell you clearly which part of the code is being executed. Eg... 'checkpoint A'.

If you KNOW the value in triggerVal, it makes no sense to print it.

    if(triggerVal == 0) {
      Serial.println(triggerVal);     // this shows me the 0

It would be impossible for it to show any other value. So, why bothering printing that?

If you printed, here, "state changed to LOW", you'd have actually learned something.

I misread above. I thought you wanted to pull the trigger and get a fade-in, and light stay on as long trigger was hold. Then you read trigger again and it was read as 0 as trigger was still active, and a new fade sequence would start.

I have bought a pack of momentary switches on ebay, but what I received was latching switches...

Back to your problem.

int lastTriggerVal = 0;
...
triggerVal = lastTriggerVal;

lastTriggerVal is initialized as 0, and is never updated.
Your first if statement is true only when trigger =1, and your second if statement will never run.

At the end of loop() try:

lastTriggerVal = triggerVal;

In English, what do you want to happen?
-When no button is pushed
-When button is pushed
-When button is held
-When button is released

majhi:
Sorry if this has been addressed before, but I can't find any other thread. I'm building a cosplay prop (lightning gun) and am having issues with an if function in my code. When I pull the trigger (momentary switch), it cues the lightning light. It's supposed to turn off, then fade on and stay on. However when I pull the trigger, it fades on, then loops the if statement forever.

So, your code is like "do this if the trigger is down", and what you actually need is "do this if the trigger is down and it has been released since the last time I did it".