{HELP} If Button high do this until that happens

Hello,i am making a counting device but after many attemts i yeald …i posted the code bellow…i cant manage to set the program to start counting only when i press the button once …i want to make it start when i press the button and stop when x=30…and start counting again from 0 to 30 when i press the button…i have problem setting the counter to stop at 30 and setting the button to start the loop again…i am so confused right now ,any help would be greatfully accepted…thank you in advance (btw im 3 days in to arduino i may do some “happy accidents” as bob said once)

#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <LightDependentResistor.h>

Adafruit_LiquidCrystal lcd(0);
const int button = 2;
int x = 0;
int buttonState =0;

void setup() {
  pinMode(button,INPUT_PULLUP); 
  lcd.begin(16, 2);
  lcd.print("X:");
  lcd.setBacklight(HIGH);
  pinMode (A0, INPUT);
  Serial.begin(9600);
}


void loop() {
  buttonState = digitalRead(button);
  lcd.setCursor(7, 0);
  int ldr = analogRead(A0);
  Serial.println(ldr);
  if (buttonState ==HIGH)
  if (ldr > 200)
   x++;
  lcd.print(x);
  delay(110);
   }

You need a variable (let's call it countInProgress) and normally it is false so no counting happens. When you press the button it is changed to true and from then on counting happens.

When you are finished counting set it back to false.

...R

Hello,i am struggling to find a way of a button working as i want it to.i want to press a button ONCE and do something until a variable x=30 …i cant make my counter stop at 30 and i also cant make it start counting when i press the button…it counts only while the button is pressed…im quite new to arduino and programming so it maybe is a silly mistake

#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <LightDependentResistor.h>

Adafruit_LiquidCrystal lcd(0);
const int button = 2;
int x = 0;
int buttonState =0;

void setup() {
  pinMode(button,INPUT_PULLUP); 
  lcd.begin(16, 2);
  lcd.print("X:");
  lcd.setBacklight(HIGH);
  pinMode (A0, INPUT);
  Serial.begin(9600);
}


void loop() {
  buttonState = digitalRead(button);
  lcd.setCursor(7, 0);
  int ldr = analogRead(A0);
  Serial.println(ldr);
  if (buttonState ==HIGH)
  if (ldr > 200)
   x++;
  lcd.print(x);
  delay(110);
   }

First a tip, press Ctrl+T to format the code more readable.

Next, you want to read a button high, how is the button connected? Do you have a pull down resistor connected? Normally it’s easier (but apparently counter intuitive for newbies) to connect a button between GND and a pin and enable the internal pull up resistors (pinMode(pin, INPUT)PULLUP)). Only now a pressed button reads LOW.

Then to the problem, I see more then only a button HIGH in line with the increment but also a variable “ldr”, what’s up with that?

And to further answer your question, don’t place the counting in side the if(buttonState ==HIGH). Only remember the button was pressed (use a variable (bool)) and only forget it was pressed once the counter reaches 30. And use the variable to see if you want to increment or not :slight_smile:

Extra tip, the use of delay() will make it hard to add things. millis() would be the non-blocking alternative.

i am struggling to find a way of a button working as i want it to.i want to press a button ONCE and do something until a variable x=30

Detecting when the button becomes pressed rather than when it is pressed would be a good start. See the StateChangeDetection example in the IDE

Once the button press has been detected set a boolean variable to true and make the actions that happen on the button press dependant on the boolean being true. Stop the actions when you need to by changing the boolean to false.

The way your program is written buttonState will change every time loop() repeats so it will go back to LOW as soon as you release the button.

You need a variable (let's call it countInProgress) which is normally false and gets changed to true when the button is pressed. Releasing the button would have no effect on the value of the variable Then, rather than

if (buttonState ==HIGH)

you would have

if (countInProgress == true)

You have another critical problem also - your IF statements are not formulated properly. The code you posted should be like this. Note how the { } group the things that are controlled by the IF

void loop() {
  buttonState = digitalRead(button);
  lcd.setCursor(7, 0);
  int ldr = analogRead(A0);
  Serial.println(ldr);
  if (buttonState ==HIGH) {
     if (ldr > 200)
        x++;
        lcd.print(x);
     }
  }
  delay(110);
}

However I'm not sure if I have grouped things the way you want them.

...R

i like the countInProgress variable...can you help me set it up? i like the logic of it..as you said it i have to move the if (buttonState==HIGH) outide of void loop? or i got it wrong ? as i type it is looks wrong to me..there is something i probably got wrong

SachpazidisGeo:
i like the countInProgress variable...can you help me set it up?

Try it yourself and if you can't get it to work then post the program that represents your best attempt and tell us what it actually does and what you want it to do that is different.

...R

okay i will..the state change detection looks to be what i want i just need to adjust it to suit my needs..i start testing and i will inform you about the condition of the project..thank you for your time and interest

Do you want to count only when the switch IS pressed, or start counting when it BECOMES pressed and continue counting when it is released.

What are you counting? It looks to me like you are counting 110 millisecond intervals, which seems like a silly thing to count.

well,i did something…not what i intented at the time but something i will need in the future fo the project…i adden an LED that will later be changed with a dc motor…the led lights until the counter reaches 30…BUT…by creating this the code just adds one every time i press the button if (ldr > 200)…i intetned to push the button and :1 start the motor ,2 whenever (ldr > 200) add one to x…when x reaches 30 stop the motor and wait untill i press the button and start again.i know there is a difference between a dc motor and an led i will set it to a pwm pin to set different speed but i put an LED just to indicate if the motor will spin or not…check the code and point me to the right way…i like the way u do not give me a simple answer and make me search it on my own it makes me “learn” some things…check the code and let me know what you think.thank you

#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <LightDependentResistor.h>

Adafruit_LiquidCrystal lcd(0);
const int button = 2;
const int ledPin = 13;
int xapia = 0;
int buttonState = 0;
int LastButtonState = 0;

void setup() {
  pinMode(button, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  lcd.begin(16, 2);
  lcd.print("X:");
  lcd.setBacklight(HIGH);
  pinMode (A0, INPUT);
  Serial.begin(9600);
}


void loop() {
  buttonState = digitalRead(button);
  lcd.setCursor(7, 0);
  int ldr = analogRead(A0);
  Serial.println(ldr);
  if (buttonState != LastButtonState) {
    if (buttonState == HIGH) {
      if (ldr > 200)
        x++;
      lcd.print(x);
      delay(110);
    }
  }
  LastButtonState = buttonState;
  if (x < 30) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

i want it start count when it BECOMES pressed and continous counting until it reaches 30..then stop and wait my push again..i am counting pills falling from a tube..the delay is not adjusted yet after i compete the arduino programming i will start testing the whole project all together to set the actual delay needed and the actual "prices" the ldr will need to work properly on that specific location taking in to consideration the different lighing of the roomi am working now and the actual room the device will be set

What happened to the idea of using a boolean to indicate that counting is in progress ?

sorry you were right i forgot it …now it adds 1 on push and 1 on release…i think did something wrong with the running section.

#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <LightDependentResistor.h>

Adafruit_LiquidCrystal lcd(0);
const int button = 2;
const int ledPin = 13;
int x = 0;
int buttonState = 0;
int LastButtonState = 0;
boolean running = false;

void setup() {
  pinMode(button, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  lcd.begin(16, 2);
  lcd.print("X:");
  lcd.setBacklight(HIGH);
  pinMode (A0, INPUT);
  Serial.begin(9600);
}


void loop() {
  buttonState = digitalRead(button);
  lcd.setCursor(7, 0);
  int ldr = analogRead(A0);
  Serial.println(ldr);
  if (buttonState != LastButtonState) {
    if (buttonState == HIGH)
      running != running;
    {
      if (ldr > 200)
        x++;
      lcd.print(x);
      delay(110);
    }
  }
  LastButtonState = buttonState;
  if (x < 30) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

You don't need ANY delays.

Look at the state change detection example, to see how to start the process when the switch BECOMES pressed.

You can use the same idea - the LDR becomes blocked/the LDR becomes unblocked - to count the pills.

It seems, though, that an LDR is NOT the correct device for you to be using. They are way too slow to react to changes in light. A phototransistor is orders of magnitude faster to react.

running != running;

This changes the state of running from true to false or false to high. What you need to do us to set it explicitly to true when the button becomes pressed and false when your end condition becomes true.

Wrap the code that checks the LDR in a test of the running variable and only execute it if it is true. The testing of the button and the testing of the running and hence the LDR are separate blocks of code. Do not make them dependant on one another.

This changes the state of running from true to false or false to high.

No it doesn't.
The ! is the wrong side of the =

No it doesn’t.
The ! is the wrong side of the =

Oh yes, so it is !

Luckily my advice was still correct even though my description of the problem was wrong

This is a duplicate of http://forum.arduino.cc/index.php?topic=533564.msg3637118#msg3637118

This is a duplicate of http://forum.arduino.cc/index.php?topic=533495.msg3636688#new