Servo Control with three buttons. (resolved and working!!!)

Thanks... was just wondering they somehow might bundle some lines together. (In a way similar to the {} after an if, where without them, only the first xyz; gets recognised.)

They can do that. That's why I wanted OP to fix his code, to see where that might be happening.

In the end I am going to build a coin operated salt and pepper dispenser. When a coin is put in the slot, it will trigger a momentary button (buttonA). After that, I want the customer to have the option to choose between salt and pepper (buttonB and buttonC). The problem is that the current code states that if the coin button (buttonA) is pressed, then the user needs to select their seasoning (buttonB or buttonC) simultaneously in order for the servo to turn. I would like to allow the user to insert a coin, and then take their own sweet time to choose from salt or pepper, similar to modern day pop machines. How could I do this?

Create a boolean variable, armed, initialized to false. Read the state of switch 1. If it is pressed, set armed to true.

Read the state of switches 2 and 3. If either is pressed and armed is true, move the servo, do whatever else needs to be done, AND set armed to false.

There is absolutely no need for interrupts - buttons are slow.

You have said you want to press BtnA and a short time later press BtnB or BtnC. It seems to me that BtnA is just an unnecessary complication. Why not reduce the code to just two buttons?

If there is a need for BtnA it makes the logic a great deal more complex. What happens if neither BtnB or BtnC is pressed?

Perhaps you need a program that ignores BtnB and BtnC if BtnA has not been pressed. Then a press of BtnA is recorded in a variable and that allows BtnB or BtnC to be recognized. However if neither B nor A is pressed within X seconds the variable set by A is unset and BtnA will need to be pressed again if anything is to happen.

But this all seems unnecessarily complicated.

...R

Yeah sorry I agree, my interrupt idea is crazy....

PaulS:
Create a boolean variable, armed, initialized to false. Read the state of switch 1. If it is pressed, set armed to true.

Read the state of switches 2 and 3. If either is pressed and armed is true, move the servo, do whatever else needs to be done, AND set armed to false.

That's basically what he has, come to think of it. Button A's state of high, is armed, and he's checking B and C only inside the if A is high part anyway, so the thinking is good I reckon.

Just cheat and add a couple of delays for now, between the state checks, else button B will be false becasue the user was too slow. As I said earlier, remember to set them low once the move is done.

And you already have them set low at the beginning.

For real life you might want a coin return if the money is inserted but they change their mind. So have a button D that forces button A's state low when pressed, and cancels the transaction.

EDIT.... but take those extra { } pairs out just in case

Robin2:
Perhaps you need a program that ignores BtnB and BtnC if BtnA has not been pressed. Then a press of BtnA is recorded in a variable and that allows BtnB or BtnC to be recognized.

That's basically what he has: B and C are only tested inside an if, when A's state is high.

I'm thinking his problem right now is a combination of no delays to give time to press B or C, and not resetting the states after the servo moves..... and maybe those extra {} pairs.

You mean like this?

if (AState == HIGH){
    delay(1000);
        if (BState == HIGH){
          myservo.write(50);
          delay(1000);
          myservo.write(111);
          delay(1000);
         
        }
      }
      else
        myservo.write(90);

No that won't work, I think I mean ( 8) ) between the lines where the buttons are actually read, so that after A is read it pauses and hopefully by the time the delay is over, the finger will be on B or C

?????

{
  AState = digitalRead(buttonA); // read and save to the variable "AState" the actual state of button
  delay(1000);
    BState = digitalRead(buttonB); // read and save to the variable "BState" the actual state of button
   
      CState = digitalRead(buttonC); // read and save to the variable "CState" the actual state of button

When I ran this it did not work at all. How confusing.

You make any other changes at the same time? Maybe post the whole code again.

No need for any delays. Re-read reply #15. PaulS gave you the necessary algorithm there.

We did it, we did it!!! I ended up using PaulS's boolean variable idea.

Create a boolean variable, armed, initialized to false. Read the state of switch 1. If it is pressed, set armed to true.

Read the state of switches 2 and 3. If either is pressed and armed is true, move the servo, do whatever else needs to be done, AND set armed to false.

Here is the working code for those who are interested. Thank you to everyone who helped me, especially PaulS and JimboZA! I hope to finish this project this weekend and start making a small profit next week. Thanks so much. -icecats-

#include <Servo.h>

Servo myservo; // creating myservo object
int buttonA = 2; // one side of buttonA attached to pin 2 and 10K resistor to ground, while other is on +5V
int buttonB = 3; // one side of buttonB attached to pin 3 and 10K resistor to ground, while other is on +5V
int buttonC = 4;  // one side of buttonC attached to pin 4 and 10K resistor to ground, while other is on +5V
int servoPin = 11;  //servo attached to pin 11
int AState = 0; // set AState 
int BState = 0; // set BState
int CState = 0; // set CState
int armed = false;

void setup()
{
  myservo.attach(servoPin); 
  pinMode(buttonA, INPUT); 
  pinMode(buttonB, INPUT);
  pinMode(buttonC, INPUT);
}


void loop()
{
  AState = digitalRead(buttonA); // read and save to the variable "AState" the actual state of button

  BState = digitalRead(buttonB); // read and save to the variable "BState" the actual state of button

  CState = digitalRead(buttonC); // read and save to the variable "CState" the actual state of button
  if (AState == HIGH){
    armed = true;
  }
  if (BState == HIGH && armed == true){
    armed = false;
    myservo.write(50);
    delay(1000);
    myservo.write(111);
    delay(1000);

  }
  else
    myservo.write(90);

  if(CState == HIGH && armed == true){
    armed = false;
    myservo.write(130);
    delay(1000);
    myservo.write(70);
    delay(1000);
  }
  else
    myservo.write(90);

}

wildbill:
No need for any delays. Re-read reply #15. PaulS gave you the necessary algorithm there.

And he's doing that already.

BUT, as soon as A is pressed it checks B right away. The OP doesn't want them to have to press them simultaneously, so if the user isn't infinetsimally quick on B, it'll read B as low.

icecats:
We did it, we did it!!!

Excellent.

Here is the working code for those who are interested.

Um.... where?

Sorry... I'm forgetful today... first the question and now the code. I have added it to the my post #24. Thankyou

Slapping myself for just twigging to the fact that A being set high near the top of loop() isn't persistent through subsequent visits, while of course the armed variable is, until it's deliberately reset. Sorry PaulS, wildbill and Robin2....

Now I'm interested to hear how many doses of salt and pepper the OP is going to have to sell to recoup the cost of an Arduino, servo, coin machine and so on....

I already had all of the parts, as electronics and Arduino is my hobby. However, I see your point. I plan on eventually making this permanent using a bare bones arduino such as Cheapduino($5:00 a piece). Cheapduino (5PCS) - DFRobot
Maybe eventually, I will make a small profit :). Thanks for all of your input, and for helping me complete this project.
-icecats-
May middle schoolers forever have seasoning...

I'm keen to see it in action

Yes, it will be a few days, but I will try to send/post you a video/pictures of some sort.

I'm happy that you have it working, but there are a couple of points I'd like to make.

int armed = false;

That's not a boolean.

boolean armed = false;

is.

  if (BState == HIGH && armed == true){

BState == HIGH evaluates to true if BState contains HIGH. armed == true evaluates to true if, and only if, armed contains true. Since the contents of armed are equal to the result returned by the == operator, the == true bit is unnecessary. This would be written:

  if (BState == HIGH && armed)
  {

The magic numbers used to define where the servo moves to should be #define'd, so that the positions have names. It makes it a lot easier to understand the code later.

1000 milliseconds is a LONG time to dispense salt or pepper, no matter how bland the food. That magic number should be #define'd, too.