logic help

hello,
i am having a very hard time wrapping my brain around how to program this logic…

A user would press one button (I have some SPST buttons from radio shack) that would send a signal to an arduino to trigger some relays that would press buttons on a digital photo frame that would start a video, play the video, and turn off the frame when it’s done, waiting for another state change to start the video back up again.
The buttons I have are either HIGH or LOW. I need to use them in the analog inputs because i’m using all the digital ones. When I have the button in analog I get a reading of 0 when it’s LOW and something 20-200 when it’s HIGH.
So every time I press the button, I want something to happen, and then stop and wait. Instead, when I press the button once, I get a loop, where Serial.println keeps repeating the test text I have…when I press the button again, nothing happens…
I set a boolean switch but the if conditional keeps looping. When the button state changes, it stops, but when it changes again it starts looping and doesn’t stop.
I also am stumped as to how to make it so that if someone presses the button during the video play that the video won’t start to play again right after…
Here is the test program I have so far:

//button is either greater than 20 or less than 20
//the button state changes between those numbers
//turn the photo frame on, run the vid, 
//while running vid make sure other button presses aren't registered
//turn it off and do nothing while waiting for another change
int buttonState;
int buttonValue;
int oldButtonState;
boolean prevent;

void setup() {
  Serial.begin(9600);

}

void loop() {
buttonValue = analogRead(0); //read it and see it the button is below 20 or above

//normalize the readings because it gives random numbers (but they're all above 20 if it's HIGH)
if (buttonValue > 20) {
  buttonState = 30; //HIGH
}
if (buttonValue < 20) {
  buttonState = 0;  //LOW
}

//check to see if it changed
//if there's no change, don't do anything
//if it changed, turn on vid, turn off and wait
//this isn't working...it keeps looping. I don't understand why if the "prevent" boolean is set to true in the conditional. 
if((oldButtonState != buttonState)&&(prevent==false)) {
  Serial.println("Turn on lcd");
  delay(200);
  Serial.println("Play video");
  prevent = true; 
  delay(2000);
  Serial.println("Turn off lcd");
  delay(200);
  Serial.println("Wait for another change");
  delay(200);
  
}
if (oldButtonState == buttonState){
  prevent = false;
}

oldButtonState = buttonState;

}

When I have the button in analog I get a reading of 0 when it's LOW and something 20-200 when it's HIGH.

That sounds like you have got the button connected between the analogue input and ground. No pull up resistor? It seem the input is floating. Why are you not using a digital input for the button? See:-

http://www.thebox.myzen.co.uk/Tutorial/Inputs.html I know it isn't solving your logic problem but you are best getting the hardware right first as it will eliminate the need for a lot of code and you might be seeing false presses when the button is released.

Thanks so much for your help. That page helped explain a lot...so now I have the button wired up correctly. I'm using the analog inputs because the digital ones will all be used when I have everything wired up. So my code is shorter now...still having the same problem as explained above. Here is what I have now:

//button is either 0 or 1023
//if the button state changes between those numbers
//turn the photo frame on, run the vid, 
//while running vid make sure other button presses don't prevent it from shutting off when done
//turn it off and do nothing while waiting for another change
int buttonState;
int oldButtonState;
boolean prevent;

void setup() {
  Serial.begin(9600);
}

void loop() {
buttonState = analogRead(0); //read it and see it the button is below 20 or above

//check to see if it changed
//if there's no change, don't do anything
//if it changed, turn on vid, turn off and wait

if((oldButtonState != buttonState)&&(prevent==false)) {
  Serial.println("Turn on lcd");
  delay(200);
  Serial.println("Play video");
  prevent = true; 
  delay(2000);
  Serial.println("Turn off lcd");
  delay(200);
  Serial.println("Wait for another change");
  delay(200);
  
}
if (oldButtonState == buttonState){
  prevent = false;
}

oldButtonState = buttonState;

}

You can use analog pins as digital pins:

For example instead of

void setup() {}
void loop(){
bool pinIsPressed = analogRead(pinNumber) > thresholdValue;
}

you could do

void setup() {
pinMode(pinNumber, INPUT); // set as digital input
digitalWrite(pinNumber, HIGH); // set pullup resistors
}
void loop() {
bool pinIsPressed = ! digitalRead(pinNumber); // not pressed is HIGH, pressed is LOW
}

hi, thanks so much for your help. it doesn't matter if the pins on the button are digital or analog, right? i mean...whether or not i get a HIGH/LOW or 0/1023 reading doesn't matter...I can still use a logic algorithm to do what i want to do, right? anyone know what i'm doing wrong with my logic? thanks!

You can set a flag when the button is pressed to indicate that action is occurring. When you read the button, if the flag is already set, then do nothing. If the flag is clear, allow the action to start. When the action is done, clear the flag to enable the next button push to start it again.

treebykooba: hi, thanks so much for your help. it doesn't matter if the pins on the button are digital or analog, right? i mean...whether or not i get a HIGH/LOW or 0/1023 reading doesn't matter...I can still use a logic algorithm to do what i want to do, right? anyone know what i'm doing wrong with my logic? thanks!

You need to do digitalRead on analog pins and compare with HIGH or LOW. So analog pin 0 is digital pin 14 and so on.

thanks for your help...I don't understand how having digitalRead would help solve my logic problem above?

treebykooba:
thanks for your help…I don’t understand how having digitalRead would help solve my logic problem above?

You don’t want to compare an analog read result with digital HIGH or LOW. That won’t help making your logic better but will make sure whatever logic you have now is actually implemented with the right commands.

I think the button flag thing is totally useless. While arduino is busy doing the digital frame operation, it naturally ignores the button so no need to read flags. If it helps, use a button library and keep calling button.sense() and start the digital frame sequence if the return is button_Pressed. You can try my button library. It’s simple and many use it for basic button handling.

You will be doing:

#include <phi_buttons.h>

#define btn_a 5

phi_buttons btn_1(btn_a, LOW);

void setup(){

Serial.begin(9600);

}

void loop(){

int temp=temp1=btn_1.sense();

if (temp==buttons_released) Serial.println("Button pressed, time to display video");
delay(3000); // video is playing

}

thanks so much for your help! that library works better than what i had before…however a lot of times it seems to not sense() when i’m pressing the button…it seems fairly erratic…sometimes it notices I press it and sometimes it doesn’t…it seems that I have to press the button twice…it’s one of those buttons that’s either HIGH or LOW…not the one that you press and it’s only HIGH when you’re pressing it…could this be why? this is my code:

#include <phi_buttons.h>
#define btn_a 7

phi_buttons btn_1(btn_a, LOW);

void setup(){

Serial.begin(9600);

}

void loop(){

int temp=btn_1.sense();

if (temp==buttons_released){
  Serial.println("Turn on");
    delay(200);
    Serial.println("Play");
    delay(2000);
    Serial.println("Turn off");
    delay(200);
    Serial.println("Wait for next press");
    delay(200);
}

}

You can do this following trick

Instead of doing just one sensing per loop you do it for a set period of time:

change
temp=btn_1.sense(); into

temp=wait_for_press(20);

This will keep sensing the button for 20 milliseconds, which is enough to get the key press. The return value is 1 if the button is pressed and 0 if not pressed and 20 milliseconds expired.
Just add the following code to your program outside of loop, in the end of the program.

int wait_for_press(int ref_time) // Returns key pressed or 0 if time expires before any key was pressed.
{
//Wait on button push.
  long temp0;
  byte temp1;
  temp0=millis();
  do
  {
      temp1=btn_1.sense();

      if((temp1==buttons_released)||(temp1==buttons_held))
      {
        return(1);
      }
  }   while ((millis()-temp0<ref_time));

  return (0);
}

BTW, the button class will automatically repeat key press after holding for 1 second and fast repeat after 10 regular repeats, quite convenient for adjusting values in a large range, like minutes on alarm clock.

thanks so much!this looks great! maybe i’m missing something, though…I’m not getting anything in my Serial.println now…
here is my code:
thanks again for the help!

#include <phi_buttons.h>
#define btn_a 7

phi_buttons btn_1(btn_a, LOW);

void setup(){
  Serial.begin(9600);
}

void loop(){

  int temp = wait_for_press(20);

  if (temp==buttons_released){
    Serial.println("Turn on");
    delay(200);
    Serial.println("Play");
    delay(2000);
    Serial.println("Turn off");
    delay(200);
    Serial.println("Wait for next press");
    delay(200);
  }

}

int wait_for_press(int ref_time) // Returns key pressed or 0 if time expires before any key was pressed.
{
  //Wait on button push.
  long temp0;
  byte temp1;
  temp0=millis();
  do
  {
    temp1=btn_1.sense();

    if((temp1==buttons_released)||(temp1==buttons_held))
    {
      return(1);
    }
  }   
  while ((millis()-temp0<ref_time));

  return (0);
}

The wait_for_press returns 1 if there is a key press so do this:

Replace

if (temp==buttons_released)

with

if (temp==1)

hmmm...now it is very erratic again. when i press the button the if (temp==1) condintional just keeps looping until i press the button again...and then it stops. any other ideas? thanks!

Maybe you held on to the button for over 1 second that triggered the hold. Remove all the delay(200) and try again :) The delays block button sensing so some button actions are not sensed and the button may not work well if part of the action was not sensed.

i took out the delays...now it just plays the if conditional on a loop until i press the button...when i press it, it stops, when i press it again, the loop starts again. i just want it to play a video and then stop and wait for another button press...i need the delays in there because there needs to be delays in between the arduino triggering the relays...

could this be because this library might not be for buttons that are either HIGH or LOW?

this is my other program i wrote...it works fine...it's just that while the video is playing i don't want it to register any button presses:

int buttonState;
boolean occuring;
int oldButtonState;

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

void loop() {
  buttonState = digitalRead(7);

  if (oldButtonState != buttonState) {
    Serial.println("Turn on");
    delay(200);
    Serial.println("Play");
    delay(2000);
    Serial.println("Turn off");
    delay(200);
    Serial.println("Wait for next press");
    delay(200);
  } 

  oldButtonState = buttonState;
}

I doubt your code works on the basis of lacking the necessary logic to recognize a press. But you said worked for you and you're ok with it so feel free to revert back. My code works fine for this button but I don't know why it didn't work for you. Did you hold the button or did you give it a quick press? I assume your button is tactile, not a click on click off. Maybe you have a click on click off button, which is why you keep getting this problems. Pictures please.

i'm using one of these buttons:

http://www.radioshack.com/product/index.jsp?productId=2062544

it is a click button...pushes on and off. is this the problem?

i have it set up with a 1k pull up resistor...like on this page: http://www.thebox.myzen.co.uk/Tutorial/Inputs_files/shapeimage_9.png

could it be because i'm using a 1k and not 3k like in the diagram?

thanks so much for all the help

I guess I was right. That was a push on push off button. You should use this:

http://www.radioshack.com/product/index.jsp?productId=2062510

Read this for how to use internal pullup resistor. Your pullup is fine but you don't have to. Just connect button to pin 7 and gnd.

http://www.arduino.cc/en/Reference/DigitalWrite

bummer...well...i'm sort of visually attached to that button. this is for a visual art project. is there any way to write code to make this button behave like the other one? or is it pretty much impossible?

thanks again for all the help.