Hi, guys. I'm a newbie in this Arduino programming.
I have a question. Can I put a conditional statement inside another conditional one?
I mean, I tried to put this "if" inside my "while" code, and vice versa. I even used "if" inside "if" or "while" inside "while". But the conditional statement inside another conditional can't be executed. Is this a problem with my code, or Arduino indeed doesn't allow that kind of code?
Here is my code.
int button1Pin = 1;
int button2Pin = 2;
int driverPin = 0;
int buzzerPin = 3;
void setup ()
{
pinMode (button1Pin, INPUT);
pinMode (driverPin, OUTPUT);
pinMode (button2Pin, INPUT);
pinMode (buzzerPin, OUTPUT);
}
void loop()
{
while (digitalRead(button1Pin) == LOW)
{
digitalWrite(buzzerPin, LOW);
digitalWrite(driverPin, HIGH);
delay(1000);
digitalWrite(buzzerPin, HIGH);
if (digitalRead(button2Pin) == LOW)
{
digitalWrite(buzzerPin, LOW);
digitalWrite(driverPin, HIGH);
delay(1000);
digitalWrite(driverPin, LOW);
}
}
I do appreciate your respond. Thanks before.
Yes, you can put an "if" inside both an "if" and a "while".
The problem is your buzzerPin is basically, always low, and your driverPin is basically, always high (except for a few microseconds), no matter whether the "if" is true or false.
That should work, barring two things:
-
Switches not wired correctly (if the two buttonpins are connected to one side of a switch, without a pullup or pulldown resistor, they will not return the value you expect when the switch is open. The usual way to do a button is to connect one side to ground, and the other side to the button pin, and then do pinMode(pin,INPUT_PULLUP), and adjust code so LOW means pressed and HIGH means not pressed. Otherwise, you need an external pullup or pulldown resistor)
-
You're pressing the button during that 1-second delay. During that delay, it's just sitting there - it'll only check for a press on button2 once per second, because it's spending the rest of the time in delay. See the abundant topics on "doing multiple things at once" on how to rewrite your code to avoid (ab)using delay()
int button1Pin = 1; // to assign pins, I usually do, const byte button1Pin = 3;
// int is integer for big nos byte is enough for you const = fixed(unchanged)
int button2Pin = 2; // also I always leave pin 0 and pin1 for debugging (these two pins are
int driverPin = 0; //for serial communications +uploading your sketch)
int buzzerPin = 3;
void setup ()
{
pinMode (button1Pin, INPUT); // use INPUT_PULLUP here for your button pins (internal pullup)
pinMode (driverPin, OUTPUT); // so your two button pins = HIGH now
pinMode (button2Pin, INPUT);
pinMode (buzzerPin, OUTPUT); // just hook up your two buttons to these two pins to the gnd(ground)
}
void loop()
{
while (digitalRead(button1Pin) == LOW) // when you press the button, digital read will see a LOW
{
digitalWrite(buzzerPin, LOW); // double check the logic of your code here
digitalWrite(driverPin, HIGH);
delay(1000);
digitalWrite(buzzerPin, HIGH);
if (digitalRead(button2Pin) == LOW)
{
digitalWrite(buzzerPin, LOW);
digitalWrite(driverPin, HIGH);
delay(1000);
digitalWrite(driverPin, LOW);
}
}
}
When it is LOW, the code inside { } is executed(the while loop continues to loop)until (digitalRead(button1Pin) == LOW // you press the button it goes from HIGH to LOW
is no longer true ( it becomes false)
http://www.arduino.cc/en/Reference/While
Also check out the example in your IDE 02 digital --debounce
to see how you debounce your switch if your buttons act weird
or look for hardware debouncing
Please edit your post, select the code, and put it between [code] ... [/code] tags.
You can do that by hitting the "Code" icon above the posting area. It is the first icon, with the symbol: </>
How to use this forum
I've tried anything possible to make it right, but still, that button1Pin inside "while" syntax will always be LOW, whether in the end of statement I put it HIGH or not.
How if,
- I want to make a program that can turn an LED on, when I press the button. I mean, that LED will be on when there's a "low to high" condition, so even if I release the button, the LED will be still.
- Then, for a few microseconds later, it will be off by itself.
- And then, when I press the same button once again, I want the buzzer to be on.
That's where I can't get it right. I can make the code for problems 1 to 2. But for the 3rd one, I need a new conditional statement inside that first "while". And anything I tried can't execute that 3rd which makes my program goes back to execute statement 1 to 2, so that's why I assumed before that Arduino doesn't allowed multiple conditional code.
There's no problem with the wire anyway. I've checked it twice.
Any idea?
Thanks again for your responds.
rahayuno:
There's no problem with the wire anyway. I've checked it twice.
Any idea?
The problem is the code as noted in answer#1, not the wiring. The results you are seeing are exactly what I would expect from the code you posted.
Sorry, I cannot understand your description of what you are trying to do.
Please try to describe it again so we can help you.
Maybe use pseudo-code, like:
loop()
{
if (button transtitions to ON)
{
turn on LED for 1 second.
turn off LED.
}
}
etc.
rahayuno:
... so that's why I assumed before that Arduino doesn't allowed multiple conditional code.
Look at this video http://www.youtube.com/watch?v=sLvgW_zb6bQ
See this blog: Peten Paja: Toorum's Quest II - Retro video game and console
That guy made a video game with an Arduino Uno.
Now once you have watched that, retract the assumption that "Arduino doesn't allowed multiple conditional code".
I've tried anything possible to make it right, but still, that button1Pin inside "while" syntax will always be LOW, whether in the end of statement I put it HIGH or not.
Post your new code with the "anything possible" in it. In code tags.
- I want to make a program that can turn an LED on, when I press the button. I mean, that LED will be on when there's a "low to high" condition, so even if I release the button, the LED will be still.
- Then, for a few microseconds later, it will be off by itself.
- And then, when I press the same button once again, I want the buzzer to be on.
You want a button to activate a buzzer if it has already activated an LED for a few micro seconds. Ask yourself how your brain would work through this logic. It would realise that it had already lit the LED and therefore on the second click it would activate the buzzer.
Easiest way to implement this in code is using a state machine:
switch( current_state )
{
case activate_light_led:
{
if( switch == HIGH )
{
//set LED to on here
current_state = light_led_wait;
led_on_time = millis();
}
}
break;
case light_led_wait:
{
if( millis() - led_on_time > 20 ) // ... or however long you want led on for
{
// turn LED off here
current_state = activate_buzzer;
}
}
break;
case activate_buzzer:
{
if( switch == HIGH )
{
// activate_buzzer here
current_state = activate_light_led; // go back to first state and start over, or whatever you need to do instead.
}
}
break;
}
As a side note, I don't know if the Arduino can time at a microsecond level, as millis() is obviously thousands of times greater than your requirement. Maybe someone else knows the answer to that.
micros() times to a 4 µS resolution (because of the way the prescaler is set up).
You can time with a 62.5 nS resolution (using a clock of 16 MHz) if you use Timer 1 or Timer 2 and set the prescaler to 1.
Not that I think it applies in this case.
arduinodlb:
Sorry, I cannot understand your description of what you are trying to do.
Please try to describe it again so we can help you.
Maybe use pseudo-code, like:
loop()
{
if (button transtitions to ON)
{
turn on LED for 1 second.
turn off LED.
}
}
etc.
here's what i want:
while (button low)
{
led on;
delay for a few seconds;
buzzer on;
if (button low) // i mean if i press the same button for the next time
{
buzzer off;
}
}
this is different from my last "what i want" before. but still, it need the same multiple conditional things.
thank you.
then inside that while loop (when button is low), i try to rewrite the button's logic as high, so the next if statement will be executed. but this doesnt help. i simulated this with proteus, anyway.
and about my previous assumption, i retract it. :3
here's my last code:
int buttonPin = 2;
int driverPin = 13;
int buzzerPin = 3;
void setup ()
{
pinMode (buttonPin, INPUT_PULLUP);
pinMode (driverPin, OUTPUT);
pinMode (buzzerPin, OUTPUT);
}
void loop()
{
digitalWrite(driverPin, LOW);
while (digitalRead(buttonPin) == LOW)
{
digitalWrite(driverPin, HIGH);
delay(1000);
digitalWrite(buzzerPin, HIGH);
int buttonState = digitalRead(buttonPin);
buttonState = HIGH;
while (buttonPin = LOW)
{
digitalWrite(buzzerPin, LOW);
}
}
}
Reading that pseudocode, I get the answer that the LED is never switched off. The buzzer will always sound unless you press the button, but you have to hold the button down "for a few seconds" while you wait for the delay to expire otherwise it won't detect that you've pressed the button.
How if,
- I want to make a program that can turn an LED on, when I press the button. I mean, that LED will be on when there's a "low to high" condition, so even if I release the button, the LED will be still.
- Then, for a few microseconds later, it will be off by itself.
- And then, when I press the same button once again, I want the buzzer to be on.
What happens after step 3? Does the buzzer sound for a fixed time or do you turn it off with the button? After the buzzer is off, what happens after that? Do we go back to the start and the next press of the button will light the LED?
(posts got crossed, so I'll answer the one with code #13)
int buttonState = digitalRead(buttonPin);
buttonState = HIGH;
while (buttonPin = LOW)
You have a couple of errors here. You read the button input into the variable buttonState but then you don't look at it - you just write HIGH into that variable.
Then you try to look at the value of buttonPin, which is 2. It can't be HIGH or LOW.
But you've actually assigned the value LOW to the buttonPin. I expect you meant ==
which is the comparison operator, instead of =
which is the assignment operator.
MorganS:
(posts got crossed, so I'll answer the one with code #13)
You have a couple of errors here. You read the button input into the variable buttonState but then you don't look at it - you just write HIGH into that variable.
Then you try to look at the value of buttonPin, which is 2. It can't be HIGH or LOW.
But you've actually assigned the value LOW to the buttonPin. I expect you meant ==
which is the comparison operator, instead of =
which is the assignment operator.
I use that buttonState just to remind my program that my buttonPin (via buttonState) has been HIGH, so the next time I press the button, it should be LOW, so the statement inside if can be executed. I can't write my buzzerPin as HIGH since it is an output.
I've tried to changed that while (buttonPin = LOW) with ==. And now my led will be off after that delay(1000), whereas I didnn't make any code about turning it off.
int buttonPin = 2;
int driverPin = 13;
int buzzerPin = 3;
void setup ()
{
pinMode (buttonPin, INPUT_PULLUP);
pinMode (driverPin, OUTPUT);
pinMode (buzzerPin, OUTPUT);
}
void loop()
{
digitalWrite(driverPin, LOW);
while (digitalRead(buttonPin) == LOW)
{
digitalWrite(driverPin, HIGH);
delay(1000);
digitalWrite(buzzerPin, HIGH);
int buttonState = digitalRead(buttonPin);
buttonState = HIGH;
while (buttonPin == LOW)
{
digitalWrite(buzzerPin, LOW);
}
}
}
I just read that Petri's blog and had a look at his retro console game. Wow, what an amazing guy. Great to see a game like the way they used to be made in the 80's. Great post BTW.
int buttonState = digitalRead(buttonPin);
buttonState = HIGH;
Why read it if you are going to overwrite it on the next line?
while (buttonPin == LOW)
Why are you testing a pin index for a LOW state? As it happens this while() loop won't execute, on the plus side it won't lock either 
I wrote a long answer, but it got lost by the system, so here's the short answer.
Your if inside while concept is the wrong way to do this. It can be done that way, but the logic is unnecessarily complicated. Much more complicated than you are ready to understand.
The right way to do this is a simple state machine, as mentioned above:
so:
boolean firstPush = true;
loop()
{
if (button transtitions to high)
{
// button has been pushed
if (firstPush == true)
{
do first push actions
}
else
{
do second push actions
}
// we pushed the button, and did the actions, so now we need to toggle the first/second
// push state
firstPush = !firstPush // toggle first/second push state
}
}