Switch Case Problem

Hi all,

***I have this question posted in a similar thread but since I've tried solving the problem with the specific "switch state" style of code I figured it might warrant a different subject.

Here's what I'm trying to do.

I've got a motor and I've got an electro mechanical valve (basically just a coil that when energized pulls a piston that allows water to flow out).

The motor has 2 positions, UP and DOWN.

Here's what I'm asking of the Arduino:

  1. I want to press a momentary button to start the program
  2. The motor will then lower to its DOWN position and shut off via a closed circuit reading from a roller switch (basically a LOW signal)
  3. A few seconds later I would like the valve to fire open and then close a few seconds after.
  4. Then, I would like the motor from step 2 to raise back to the UP positions (this can be a function of time and does not interface with the roller switch).

Several people have suggested switch statement code and I've done a bunch of searches and countless youtube videos in an attempt to better understand it and I'm still stuck.

I've attached the code that I've got so far. Any suggestions or points towards other materials where I can better educate myself would be AWESOME!!!!

  const byte startButton = 2;
  const byte rollerSwitch = 3;
  const byte brewMotor = 13;      
  const byte brewValve = 12;

  int readButtonState;           // the current reading from the input pin 2
  int readRollerState;           // the current reading from the input pin 3
  

void setup()  {

  Serial.begin(9600);
  
  pinMode(3, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  digitalWrite(brewMotor, LOW);
}


 void loop()  {

  int readButtonState = digitalRead(startButton);
  Serial.print ("buttonState:");
  Serial.println (readButtonState);

  int readRollerState = digitalRead(rollerSwitch);
  Serial.print ("rollerState:");
  Serial.println (readRollerState);
  
  switch (readButtonState)
  {
  
    case 1: //push the button to turn motor on
      if (readButtonState == LOW)
      {
        digitalWrite(brewMotor, HIGH);
      }
      break;
    
    case 2: //an external roller switch tells Arduino to turn motor off
      if (readRollerState == LOW)
      {
        digitalWrite(brewMotor, LOW);
      }
      break;
    
    case 3: //if the roller switch tells the Arduino to turn motor off and the button state is low, then 
                 turn the brewVavle on
      if (readRollerState == LOW && readButtonState == LOW)
      {
        delay(1000);
        digitalWrite(brewValve, HIGH);
        delay(5000);
      }
      break;
    
    case 4: // if the roller switch tells the Arduino to turn motor off and the button state is low, then 
      turn brewMotor on for (x) seconds
      if (readRollerState == LOW && readButtonState == LOW)
      {
        delay(10000);
        digitalWrite(brewMotor, HIGH);
        delay(2000);
      }
      break;
  }
  }

The motor has 2 positions, UP and DOWN.

How can a motor have a position? It is either on of off. If on, it might be rotating clockwise or counter-clockwise. But, it is not up or down.

More importantly, why are you starting a new thread with the same crappy code?

What they have been asking you to do is create a FINITE STATE MACHINE (look this up) and the switch statement implements the FSM for you. There are lots of this discussion on the forum already.

marco_c:
What they have been asking you to do is create a FINITE STATE MACHINE (look this up) and the switch statement implements the FSM for you. There are lots of this discussion on the forum already.

Thanks Marco. I'll search around for that.

PaulS - Thanks for the great feedback! My code is crappy indeed, I just started doing this 2 weeks ago. But thanks for taking time out of your busy life to respond with productive feedback! This is a new thread because it seemed more relevant to switch state and not only to "combining code". But, as before, thanks again for the truly illuminating help.

marco_c:
What they have been asking you to do is create a FINITE STATE MACHINE (look this up) and the switch statement implements the FSM for you.

Yep, here

stueveone:
Hi all,

***I have this question posted in a similar thread but since I've tried solving the problem with the specific "switch state" style of code I figured it might warrant a different subject.

In that case you should not have continued in your other thread as well :wink:

  switch (readButtonState)

{

case 1: //move brewMotor down
      if (readButtonState == LOW)

Given that LOW is the same as zero (0) when would this "if" condition ever be true? You are saying for the switch case that readButtonState is equal to 1, test if it is also equal to 0.

  1. I want to press a momentary button to start the program
  2. The motor will then lower to its DOWN position and shut off via a closed circuit reading from a roller switch (basically a LOW signal)
  3. A few seconds later I would like the valve to fire open and then close a few seconds after.
  4. Then, I would like the motor from step 2 to raise back to the UP positions (this can be a function of time and does not interface with the roller switch).

I would find this easier to read if you made it clearer what agent is responsible for what action. Rather than saying "the motor will then lower to its DOWN position", say "the sketch should lower the motor to its DOWN position".

The sentence "shut off via a closed circuit reading doesn't tell me who does the readng, who does the shutting off. I can't tell if the ardiuno is supposed to be reading the roller switch and responding to it, or if the motor itself is deactivated by the roller pin. This is a frequent ting when people use PIR detectors - I cant tell if they are asking me to write a delay into the code, or telling me that the detector itself has a 3-second timeout.

In general, rather than "X happens", I need "Y does/will do/may do X" in the case of external stuff than happens, and "the sketch must/shall/should Z" in the case of stuff that you want the sketch to do. Using passive mode is from science and scientific experiments. That kind of language makes sense when you are recording observations of events, but not when you are specifying what a thing is required to do. Condition->agent->action.

To continue:

How is the sketch to know when the motor is fully raised? Or should it just leave the "raise" pin HIGH?

Ahhh... right. Thanks Nick. Yes, that "case 1:" should have been "case 0:" So basically the label after "case" needs to be a condition in which the switch value can read. Does that sound about right?

So basically the label after "case" needs to be a condition in which the switch value can read. Does that sound about right?

It sounds exactly right.

PaulMurrayCbr:
I would find this easier to read if you made it clearer what agent is responsible for what action. Rather than saying "the motor will then lower to its DOWN position", say "the sketch should lower the motor to its DOWN position".

Thanks for your help Paul. I've edited above and I hope it's more descriptive.

PaulMurrayCbr:
The sentence "shut off via a closed circuit reading doesn't tell me who does the readng, who does the shutting off. I can't tell if the ardiuno is supposed to be reading the roller switch and responding to it, or if the motor itself is deactivated by the roller pin. This is a frequent ting when people use PIR detectors - I cant tell if they are asking me to write a delay into the code, or telling me that the detector itself has a 3-second timeout.

So, a push button will signal to the Arduino to move the brewMotor thereby moving the associated motor arm down until the motor arm switches a roller switch from an open to closed circuit. I would like to use this roller switch to then tell the Arduino to shut the brewMotor off. I would then like about 1 second delay and then I would like the Arduino to open a brewValve (high signal from pin 12) for 5 seconds. And finally, after the brewValve closes after being open for 5 seconds, I would like the Arduino to send a signal to turn the brewMotor back on for (x) seconds.

This part is a little confusing, but I am basically wanting to be able to turn a DC motor 180 degrees until an attached arm closes a micro switch, where this signals the Arduino to stop the motor. Meanwhile, the other valve fires after a delay and is on for (x) seconds, and I am then asking the Arduino to to turn the brewMotor past that 180 mark, this time for a number of seconds, until it roughly gets back to where it started.)

PaulMurrayCbr:
In general, rather than "X happens", I need "Y does/will do/may do X" in the case of external stuff than happens, and "the sketch must/shall/should Z" in the case of stuff that you want the sketch to do. Using passive mode is from science and scientific experiments. That kind of language makes sense when you are recording observations of events, but not when you are specifying what a thing is required to do. Condition->agent->action.

To continue:

How is the sketch to know when the motor is fully raised? Or should it just leave the "raise" pin HIGH?

The sketch does not need to "know" when the motor is fully raised. I am only asking the Arduino to turn on the brewMotor for a matter of seconds, which in turn, will raise it in the ballpark.

Thanks for all your questions and feedback PaulMurrayCBR (CBR meaning motorcycle? Do you ride?)

Ok, so after reading these materials:

hackingmajenkoblog

and

teachmetomake

I decided to start from scratch working with the "brewMotor" function first (named led1 in the code) and got it to do what I want!

starting out with roughing out the states:

LED 1 (aka brewMotor)

Wait for signal from button to turn on
(pin 3 LOW)
Turn on
Wait for signal from roller to turn off
((pin 2 LOW)
Turn off and Remember time
Wait for time to pass (4 seconds)
Turn on
Wait for time to pass (2 seconds)
Turn off

// States

const int waitForSignalButton = 0;
const int turnOnLed1 = 1;
const int waitForSignalRoller = 2;
const int turnOffLed1 = 3;
const int turnOffDelayLed1 = 4;
const int turnOnLedAgain = 5;
const int turnOnDelayLed1 = 6;
const int turnOffLedAgain = 7;

// Pin Numbers

const int led1Pin = 13;
const int buttonPin = 3;
const int rollerPin = 2;

void setup()
{
  pinMode(led1Pin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(rollerPin, INPUT_PULLUP);
}

void loop()
{
  static int state = waitForSignalButton;
  static unsigned long ts;

  switch (state)
  {
    case waitForSignalButton:

    if (digitalRead(buttonPin) == LOW)  {
    state = turnOnLed1;
    }
    break;

   case turnOnLed1:
    digitalWrite(led1Pin, HIGH);

    state = waitForSignalRoller;

    break;

   case waitForSignalRoller:

    if (digitalRead(rollerPin) == LOW)  {
      state = turnOffLed1;
    
    break;

   case turnOffLed1:
    digitalWrite(led1Pin, LOW);
    
    ts = millis();  // Remember the current time

    state = turnOffDelayLed1;

    break;
    

    case turnOffDelayLed1:
    if (millis() > ts + 4000)
    {
      state = turnOnLedAgain;
    }

    break;

   case turnOnLedAgain:
    digitalWrite(led1Pin, HIGH);

    ts = millis(); // Remember the current time

    state = turnOnDelayLed1;

    break;
    
   case turnOnDelayLed1:
    if (millis() > ts + 2000)
    {
      state = turnOffLedAgain;
    }

    break;

   case turnOffLedAgain:
   digitalWrite(led1Pin, LOW);

   state = waitForSignalButton;

   break;
    
  }
}
}

Next I'm going to try and add in the "brewValve" component. I guess in a separate switch?

Next I'm going to try and add in the "brewValve" component. I guess in a separate switch?

Let me guess. That will (stupidly) be called led2.

Why not name variables and states so that they make sense?

PaulS:
Let me guess. That will (stupidly) be called led2.

Why not name variables and states so that they make sense?

Hahaha. "stupidly"... Sigh... There's always one in every forum... PaulS I'm using LEDs to prototype, so, kinda makes sense if you stop and think about it.

I'm using LEDs to prototype, so, kinda makes sense if you stop and think about it.

Not to me, it doesn't. Once you get the code working with LEDs, it hardly makes sense to then rewrite the sketch when you install the proper hardware.

Use names that reflect that the real hardware is going to be. It is fine to tell us, then, that the real hardware is being simulated by something else.

stueveone:
Next I'm going to try and add in the "brewValve" component. I guess in a separate switch?

I think you guess wrong. After all you only want to start the valve action after the motor has reached the down position. You want to keep your actions (motor down, delays, valve open, ...) synchronized which will probably add an additional layer of complexity when using multiple switch constructions.

Now that you seem to have a basic understanding how a switch construction can be used in a statemachine, I suggest that you try to understand the code that I presented in your other thread.

I agree with @PaulS that it will be better to use the real names in this case. This thread started with motors and valves and they can not be found back in your code. That makes it very difficult for those that want to help, to understand what is happening; the fact that you simulate the motor and the valve with a LED in your test setup is fine (and basically not our concern :wink: ).

stueveone:
Hahaha. "stupidly"... Sigh... There's always one in every forum... PaulS I'm using LEDs to prototype, so, kinda makes sense if you stop and think about it.

No it does not... Can't agree more with Paul. While prototyping the test board is a abstract representation of what you want to do. So a led to mimic a motor is fine. But writing code for that representation and thus calling it a led instead of a motor is just nonsense. That's the world backwards.

And the moment you start numbering (or pre/post-fixing in general) the variables it's time to switch to arrays. Will make your life a heck of a lot easier :slight_smile:

Thanks for the help/feedback/wisdom...

I certainly learned a lot and I actually got the thing working.

-s

Don't know if this will help, but its something to think about when controlling machinery.

I like to make a "truth" table of Possible inputs vs possible States.

Example would be list all your inputs across the top. User button press, limit switches etc. And States down the side. Then in each case, where a state and input cross, ask yourself what do I do if this happens?

Some cases will change your state, some can cause you to panic. Some can cause you to add more states.

Good luck!

-jim lee

Thanks jimlee, that sounds like a great idea. I know it helped a lot when I wrote down the "tranisition" and "action" steps so I'll try this technique too!

stueveone:
But thanks for taking time out of your busy life to respond with productive feedback!

But, as before, thanks again for the truly illuminating help.

Please act mature on the forums, we're not here to argue or to insult people.
People are here to help.