Switch Statement - Keep Validating

I have a motor that is hooked up to a hall effect current sensor. I make the motor go in a default direction if a button is pushed. If it senses resistance from the sensor, it drops out of it’s state and switches to a new state which says to reverse polarity and as long as the current sensor is low enough, then keep going. Once the current is too high again, then you are complete, stop the motor and jump out of the state and go back to a default, to no motor movement state.

My problem is that it keeps going to the reverse polarity state even when the current is low at the initial button push (if it’s low at the initial, then I tell it to keep going in that direction)

const int S_motorOff = 0;

const int S_buttonPressed = 1;

const int S_switchdirections = 2;

const int S_keepGoing = 3;

 

 

// this constant won't change:

const int  buttonPin = 2;    // the pin that the pushbutton is attached to

const int motorOpen = 11;

const int motorClose = 10;

const int motorInitialize = 9;

// the pin that the LED is attached to

 

// Variables will change:

int buttonPushCounter = 0;   // counter for the number of button presses

int buttonState = 0;         // current state of the button

int lastButtonState = 0;     // previous state of the button

 

//info on the hall effect sensor

/*

Measuring Current Using ACS712

*/

const int analogIn = A0;

int mVperAmp = 185; // use 100 for 20A Module and 66 for 30A Module

int RawValue= 0;

int ACSoffset = 2500;

double Voltage = 0;

double Amps = 0;

 

void setup() {

  // initialize the button pin as a input:

  pinMode(buttonPin, INPUT);

  // initialize the LED as an output:

  pinMode(motorOpen, OUTPUT);

  pinMode(motorOpen, OUTPUT);

  pinMode(motorInitialize, OUTPUT);

  // initialize serial communication:

  Serial.begin(9600);

}

 

 

void loop() {

 

//current sensor info

RawValue = analogRead(analogIn);

Voltage = (RawValue / 1024.0) * 5000; // Gets you mV

Amps = ((Voltage - ACSoffset) / mVperAmp);

 

buttonState = digitalRead(buttonPin);

Serial.println(buttonPushCounter);

  // compare the buttonState to its previous state

  if (buttonState != lastButtonState) {

    // if the state has changed, increment the counter

  if (buttonState == HIGH) {

      // if the current state is HIGH then the button

      // wend from off to on:

      buttonPushCounter++;

    

    } else {

      // if the current state is LOW then the button

      // wend from on to off:

      Serial.println("off");

    }

    // avoid bouncing

    delay(50);

  }

  // save the current state as the last state,

  //for next time through the loop

  lastButtonState = buttonState;

 

  if (buttonPushCounter % 2 == 0) {

    buttonPushCounter =0;

  }

  

  

  //set the initial OFF state for not motor movement and will revert back to after case breaking

 

   static int state = S_motorOff ;

  // To store the current time  for delays

  static unsigned long ts;

 if (buttonPushCounter ==1)

 {

  switch (state)

  {

    case S_motorOff:

      // Highway gets green, country road red

      digitalWrite(motorOpen, LOW);

      digitalWrite(motorClose, LOW);

 

      digitalWrite(motorInitialize, LOW);

 

     state = S_buttonPressed;

      break;

     

      

      

    case S_buttonPressed:

      if (buttonPushCounter ==1){

     

      ts = millis(); 

      

      Serial.print("Raw Value = " ); // shows pre-scaled value

      Serial.print(RawValue);

      Serial.print("\t mV = "); // shows the voltage measured

      Serial.print(Voltage,3); // the '3' after voltage allows you to display 3 digits after decimal point

      Serial.print("\t Amps = "); // shows the voltage measured

      Serial.println(Amps,3); // the '3' after voltage allows you to display 3 digits after decimal point

  

   

      /////////////////////////////try the motor in default direction first

      digitalWrite(motorOpen, LOW);

      digitalWrite(motorClose, HIGH);

 

      digitalWrite(motorInitialize, HIGH);

    

        ts = millis();

        

      if ((ts > (ts +1000) && (RawValue <525))) //this means if the load is more than 525 it will switch to S_switcdirections

      {

      state = S_keepGoing;
      break;}
   

      else {state = S_switchdirections;}
      
      break;
      }


    

    

     ////////do this code if the load was low enough and you want to travel in the same direction

     case S_keepGoing:

     Serial.print("forward direction");

     Serial.println(RawValue);

      if (RawValue <525){

      digitalWrite(motorOpen, LOW);

      digitalWrite(motorClose, HIGH);

 

      digitalWrite(motorInitialize, HIGH);

       

      }

       else if (RawValue >525){

         state =S_motorOff;

         buttonPushCounter =0;

         digitalWrite(motorOpen, LOW);

      digitalWrite(motorClose, LOW);

 

      digitalWrite(motorInitialize, LOW);

       break;}


case S_switchdirections:
      Serial.print("we made it here again...why does it get to this state!");
     delay(5000);
      
      }
      
      
      }}
      if ((ts > (ts +1000) && (RawValue <525)))

So to get to keep going this if has to be true. What do you think are the chances that ts will ever be greater than ts + 1000? That’s a mathematical impossibility. So it hits the else and makes state to switch direction.

Quick of you to correct my error (thank you), however, I made that > sign in desperation and quickly fixed it back to what it should be. You’re right, it’s mathematically impossible.

Anyway, still having the same issue even with > sign turned to a < sign. I also redid the code and a lot cleaner easier to read…except…this time i can’t get it to go into the switchedDirection!

I must be a hierarchy of statements problem…

const int S_motorOff = 0;

const int S_buttonPressed = 1;

const int S_switchdirections = 2;

const int S_keepGoing = 3;

 

 

// this constant won't change:

const int  buttonPin = 2;    // the pin that the pushbutton is attached to

const int motorOpen = 11;

const int motorClose = 10;

const int motorInitialize = 9;

// the pin that the LED is attached to

 

// Variables will change:

int buttonPushCounter = 0;   // counter for the number of button presses

int buttonState = 0;         // current state of the button

int lastButtonState = 0;     // previous state of the button

 

//info on the hall effect sensor

/*

Measuring Current Using ACS712

*/

const int analogIn = A0;

int mVperAmp = 185; // use 100 for 20A Module and 66 for 30A Module

int RawValue= 0;

int ACSoffset = 2500;

double Voltage = 0;

double Amps = 0;

 

void setup() {

  // initialize the button pin as a input:

  pinMode(buttonPin, INPUT);

  // initialize the LED as an output:

  pinMode(motorOpen, OUTPUT);

  pinMode(motorOpen, OUTPUT);

  pinMode(motorInitialize, OUTPUT);

  // initialize serial communication:

  Serial.begin(9600);

}

 

 

void loop() {

 

//current sensor info

RawValue = analogRead(analogIn);

Voltage = (RawValue / 1024.0) * 5000; // Gets you mV

Amps = ((Voltage - ACSoffset) / mVperAmp);

 

buttonState = digitalRead(buttonPin);

Serial.println(buttonPushCounter);

  // compare the buttonState to its previous state

  if (buttonState != lastButtonState) {

    // if the state has changed, increment the counter

  if (buttonState == HIGH) {

      // if the current state is HIGH then the button

      // wend from off to on:

      buttonPushCounter++;

    

    } else {

      // if the current state is LOW then the button

      // wend from on to off:

      Serial.println("off");

    }

    // avoid bouncing

    delay(10);

  }

  // save the current state as the last state,

  //for next time through the loop

  lastButtonState = buttonState;

 

  if (buttonPushCounter % 2 == 0) {

    buttonPushCounter =0;

  }

  

  

  //set the initial OFF state for not motor movement and will revert back to after case breaking

 

   static int state = S_motorOff ;

  // To store the current time  for delays

  static unsigned long ts;

 if (buttonPushCounter ==1)

{switch (state)
  {
    case S_motorOff:
      // Highway gets green, country road red
      digitalWrite( motorOpen, LOW);
      digitalWrite( motorClose, LOW);
      digitalWrite( motorInitialize, LOW);
      state = S_buttonPressed;
      break;
 
    case S_buttonPressed:

      Serial.println(RawValue);
      digitalWrite( motorOpen, LOW);
      digitalWrite( motorClose, HIGH);
      digitalWrite( motorInitialize, HIGH);
      ts = millis();
      if ((ts < (ts + 1000)) && (RawValue <520)) {
        state = S_keepGoing;
      }

      else if ((ts < (ts +1000)) && (RawValue>520)){
        state = S_switchdirections;
      }
     break;
        
        
     case S_keepGoing:

          digitalWrite( motorOpen, LOW);
         digitalWrite( motorClose, HIGH);
         digitalWrite( motorInitialize, HIGH);
        Serial.println(RawValue);
        Serial.print("Keeping it moving forward");
        
        if (RawValue > 525){
          digitalWrite( motorOpen, LOW);
          digitalWrite( motorClose, LOW);
          digitalWrite( motorInitialize, LOW);

      buttonPushCounter =0;
      state = S_motorOff;
        }break;


       case S_switchdirections:

        Serial.print("switching directions now");
        delay(5000);
        Serial.println(RawValue);
        ts = millis();
        if (ts < (ts+2000)){
        digitalWrite( motorOpen, LOW);
          digitalWrite( motorClose, LOW);
          digitalWrite( motorInitialize, LOW);}
        else {
          digitalWrite( motorOpen, HIGH);
         digitalWrite( motorClose, LOW);
         digitalWrite( motorInitialize, HIGH);}

         if (RawValue <485){
          digitalWrite( motorOpen, LOW);
          digitalWrite( motorClose, LOW);
          digitalWrite( motorInitialize, LOW);

      buttonPushCounter =0;
      state = S_motorOff;
        
          
          }
          break;
          
          

        
          
        }//this bracket is for the end of the case statements. all case statements must go in here
        
        }//this ends the original if statement which gets you into your States
        
        }
if ((ts < (ts + 1000)) && (RawValue <520))

Is just as useless. What do you think are the chances that ts is less than ts + 1000? I think that is going to be true every single time. Maybe you mean to have two different times there? Why are you using ts twice in that?

if ((ts < (ts + 1000)) && (RawValue <520))

What I’m trying to say is…

If you don’t hit a current spike via reaching the end of your motor movement withing the first second, then keep going in that direction by changing state to keepGoing.

else if you hit a spike, then switchDirections of motor.

If in the case I actually did this right…then could it be that upon hitting the button, of all my interger values for RawCurrent, then any of those values could start lower than 520 and therefore always uses keepGoing as my default? This seems much more likely, yet I can’t understand how to say [check to see the current reaches 520, then switch]

Go look at the "Blink Without Delay" example which you are trying to emulate. Notice how it uses a different variable for the previous time and the current time. You have to do that. Because if all you do is ask "Is right now happening before 1 second from now" then the answer is always yes and there is no reason to even ask that.

Hmmm...Delta - I know what you're saying but I'm pretty sure that is not the problem. It asks once about the time and current validation, then switches to a new state which ALWAYS reverts back to buttonPushCounter = 0. If buttonPushCounter ==0 then it never even looks to the case statements.

I can get this code to work in one direction (low load then continue low load) but not the other (high load then switch to relieve load then look for high load again).

At this point, I'm really thinking it's something to do with reading the current low when pressing the button and then always validating the code to run in default direction (as in load is low enough to keep going in this direction).

How do I tell it to ignore the first seconds of readings, then take a snapshot of the current?

delay (1000); then read the current? I think I'm on to something becuase when I put in Serial.print("blah blah blah") in the keepGoing State, it goes straight to it even if I physically hold the motor and make the current spike.

Blah freakin blah!

Well you are using the rawValue that you got way back at the beginning of loop before you turned the motor on.

When you're trying to time something you need two times. The beginning of that interval and the current time. You have to set a variable to the current time when the thing that begins the timing interval happens and then later you compare that to the current time.

What won't work is setting ts equal to millis and then comparing that to itself plus 1000.

I think this is part of your issue because it is stuffing up those if statements and causing you to go to the other state or preventing you going to the other state.