Questions on how to stop my program from looping continuously...

Hi Everyone!

So I’ve put together this program, as best I could, to basically take a couple of sensor readings and display the results through serial to my comp (eventually this will be displayed on an OLED). My issue is, my program keeps looping my hardware without prompt. Basically it will start running (turning on the led, activating the pump, etc) without any presses of my onbttn (a push button)

Then, it will keep looping. I need to change this program to not begin until prompted by the onbttn, and stop and wait for another prompt once it completes a cycle.

I’ve done some investigating, and I’ve read I can possibly use whiles or switch/cases but Im not strong in C++ so I figured, let me consult some experts first…

Heres what I have so far! Please let me know what you think would be a good solution! Thanks!!

/*-----------------------(ROOT DEFINITION & VARIABLES SECTION)----------------------------------*/

//These are component definitions 

#define vibmotor 3   
//#define bttnled1  
//#define bttnled2
//#define bttnled3
//#define bttnled4
//#define bttn 
//#define sleepbttn
#define tempSensor A2
#define dsolenoid 2
#define alcsensor A1
#define onbttn 4
#define testled 8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
#define ampon 6
#define hallsensor 7

//May be better to use int variable declarations for alcSensor as the value is specifically important
int alcSensorValue = 1023;
int alcSensorTest1 = 0;
int alcSensorTest2 = 0;
int alcSensorTest3 = 0;
int alcSensorMin = 0;
int alcSensorMax = 1023;
int onbttnvalue = 0;

void setup()
{
	Serial.begin(9600); // This defines the speed at which the board communicates and MUST match the device frequency

/*------(LIBRARIES)-----*/

/*#include <>
#include <>
#include <>*/

/*------------------------(Defining Input and Output Pins)----------------------------------*/

	pinMode(vibmotor, OUTPUT); //This is to alert users to test themselves, or confirm completion of an action
	pinMode(dsolenoid, OUTPUT); //This activates the solenoid for a specific interval of time
	pinMode(onbttn, INPUT); //This is input for the test button for the alcohol sensor functions, ****remove in final build****
	//pinMode(sleepbttn, INPUT); //This is the output for the LED behind the frosted ring
	//pinMode(bttn, INPUT); //This is the input for the button array
	//pinMode(bttnled1, OUTPUT); //This is the output for the led ring of button 1
	//pinMode(bttnled2, OUTPUT); //This is the output for the led ring of button 2
	//pinMode(bttnled3, OUTPUT); //This is the output for the led ring of button 3
	//pinMode(bttnled4, OUTPUT); //This is the output for the led ring of button 4
	pinMode(tempSensor, INPUT);	//This is the temp sensor
	pinMode(alcsensor, INPUT); //This is input for AlcSensor
	pinMode(testled, OUTPUT); //This is input for LED
	pinMode(hallsensor, INPUT);
	pinMode(ampon, OUTPUT);

/*----------------------(Calibration for Alcohol Sensor)------------------*/
	//calibrate the alcSensor
	while (millis()<5000) {
		alcSensorValue = analogRead(alcsensor);
		//record the min value
		if (alcSensorValue > alcSensorMax) {
			alcSensorMax = alcSensorValue;
		}

		//record the max value
		if (alcSensorValue < alcSensorMin) {
			alcSensorMin = alcSensorValue; 
		}
	}



}

void loop()
{
	digitalWrite(11, HIGH);
        digitalRead(onbttn);
	if (onbttn = LOW)
	{
	        digitalWrite(testled, HIGH);
		delay(5000);
		digitalWrite(dsolenoid, HIGH);
		delay(300);//<----Read and find out how long solenoid should be activated
		analogRead(alcsensor);
		alcSensorValue = alcsensor;
		digitalWrite(testled, LOW);
		digitalWrite(dsolenoid, LOW);
		digitalWrite(vibmotor, HIGH);
		delay(2000);
		digitalWrite(vibmotor, LOW);
		/*int reading = analogRead(tempSensor);
// converting that reading to voltage, for 3.3v arduino use 3.3
float voltage = reading * 5.0;
voltage /= 1024.0;
// print out the voltage
Serial.print(voltage); Serial.println(" volts");
// now print out the temperature
float temperatureC = (voltage - 0.5) * 100 ; //converting from 10 mv per degree wit 500 mV offset
//to degrees ((voltage - 500mV) times 100)
Serial.print(temperatureC); Serial.println(" degrees C");*/
		Serial.println(F("Sensor Voltage is..."));
		Serial.println(alcSensorValue);
		Serial.println(F("BAC is..."));
		//Serial.println(alcSensorValue*....) Find equation for determining BAC from Voltage
		//digitalRead(hallsensor);
		/*if (hallsensor == HIGH)
		{
			Serial.println("Door is open...");
		}
		else
		{
			Serial.println("Door is closed...");
		}*/
                digitalRead(onbttn);
                onbttnvalue == onbttn;
                while (onbttnvalue = LOW)
                {
                  digitalRead(onbttn);
                  if(onbttn>LOW)
                  {
                    loop();
                  }
                }
        }
}

This if (onbttn = LOW) should be if (onbttn == LOW)

You need == for a test. A single = is for assigning a value.

...R

10and2Inc:

#define onbttn 4

void loop()
{
       digitalRead(onbttn);
if (onbttn = LOW)
{
// your stuff
        }
}

It's hard to believe this compiles. You have a couple of problems.
-- you do digitalRead(onbttn) but do not do anything with the result
-- if (onbttn = LOW) -- the single equals is ASSIGNMENT here you are ASSIGNING onbttn to LOW
-- but #define onbttn 4 is the constant "4". This should not compile -- I haven't tried

So what you likely want is something like:

#define onbttn 4
int old_button_state = LOW;


void loop()
{
    int now_button_state;

        now_button_state = digitalRead(onbttn);
	if (now_button_state == LOW && old_button_state = HIGH)
	{
// your stuff
        }
       old_button_state = now_button_state;
}

:~ Wow...thank you guys so much. I didnt even see these issues!

Im going to try it, but Im kind of confused... Where in the program would the old_button_state become HIGH for it to fulfill the conditions of the IF statement?

Should that old_button_state be assigned to LOW? Or should something trigger it becoming HIGH? Or is there some higher level use Im way too noobed to get lol?

If you don't have an external pull-up or pull down resistor, wire your button from pin
4 to GND and change this line:

	pinMode(onbttn, INPUT); //This is input for the test button for the alcohol sensor functions, ****remove in final build****

to this:

	pinMode(onbttn, INPUT_PULLUP); //This is input for the test button for the alcohol sensor functions, ****remove in final build****

This engages the internal pullup so the pin doesn't float.

gardner:
-- you do digitalRead(onbttn) but do not do anything with the result

Full marks for sharper eyesight than mine.

...R

You can make that switch input as interrupt to call your function & keep the loop empty.

apurvdate:
You can make that switch input as interrupt to call your function & keep the loop empty.

I think it is reasonable to assume that someone who does not know how to do something without interrupts will find a solution using interrupts significantly more difficult.

...R

10and2Inc:
Where in the program would the old_button_state become HIGH for it to fulfill the conditions of the IF statement?

When now_button_state isn't LOW, it's HIGH. At the end of each loop we copy now_button_state to old_button_state.

The idea here is to catch the moment when the button state transitions from HIGH to LOW and ignore all the other cases -- ie: holding the button down, letting it go and leaving it un-pressed.

Hmmm, I see...

Thank you Gardner, thank you everyone! That was honestly an awesomely quick reply...

I will do some reading and playing around with interrupts (because I feel like I will need them in the code later). I'll probably be back lolol

You don't want an interrupt in this program. That post was a pretty bad idea. Calling functions that take a long time from an ISR is never going to work out well.

If you were to use an interrupt you would have it just set a flag that the main loop could read and react to. In that case you haven't saved yourself anything over just polling the button unless you are the fastest button pusher who has ever lived and can mash a button and get your finger back off of it in under a few microseconds.

:~ Hmmm

So Delta_G what would you suggest? And where do I find out more information on how to utilize it?

Utilize what?

Is this what you're trying to do?

int buttonPin = 7;
int lastButtonState = HIGH;

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

void loop(){
  
  int buttonState = digitalRead(buttonPin);  //this will be LOW if pressed or HIGH if not.
  
  if (buttonState == LOW && lastButtonState == HIGH){     // Button pressed this time but wasn't last time.
    Serial.print("The Button Got Pressed");
    Serial.print("I'll print this once and wait until it is pressed again.");
  }
  
  lastButtonState = buttonState;  // if button is pressed right now this will be LOW, otherwise it will be HIGH
}