Making a DC motor wait for conditions

Hi I am working on a project that uses an Arduino UNO and a motor shield to run a DC motor. The inputs are a limit switch and a light dependent resistor. I have the motor running when the input from the LDR is above 30 until I press the limit switch at which point it stops until the LDR reading drops below 30. When its below 30 the motor runs in the opposite direction as I want it to. MY issue is I can’t get it to stop after 30 seconds and wait for the light level to climb aboce 30 at which point it should all start over.

Here is the code I am using

const int
PWM_A   = 3,
DIR_A   = 12,
BRAKE_A = 9,
SNS_A   = A0;
int LDR_Pin = A1; //analog pin 1
const int buttonpin = 2;
int sensorValue = 0;
int buttonstate = 0;

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

void loop(){
  int LDRReading = analogRead(LDR_Pin); 

buttonstate = digitalRead(buttonpin); 
  Serial.println(LDRReading);
  delay(250); //just here to slow down the output for easier reading

sensorValue = analogRead(LDR_Pin);
  // read pin value
 
  if (sensorValue <= 30 && buttonstate == HIGH)
  {
    digitalWrite(BRAKE_A, LOW);  // setting brake LOW disable motor brake
    digitalWrite(DIR_A, HIGH);   // setting direction to HIGH the motor will spin forward
    analogWrite(PWM_A, 255);
    
    delay (4000);
    analogWrite(PWM_A, 0);
  }
   
    if (sensorValue > 30 && buttonstate == LOW){
    digitalWrite(BRAKE_A, LOW);  // setting brake LOW disable motor brake
    digitalWrite(DIR_A, LOW);   // setting direction to HIGH the motor will spin forward
    analogWrite(PWM_A, 255);
    
    delay (4000);
    analogWrite(PWM_A, 0);
    }
}

Cheers

  int LDRReading = analogRead(LDR_Pin); 
sensorValue = analogRead(LDR_Pin);

Why do you have two different statements for reading the light level?

I think you need to separate your light level and switch reading logic from the action. You need to decide that it is time to move the motor based on the light level. You need to implement that action only if the light level has been at that level for a sustained period of time. When the motor is moving, you need to read the state of the switch, and stop the motor as needed. There is no need to read the switch if the motor isn't moving, is there?

Of course as you can't check the elapsed time or your sensors when using delay() you need to learn to do without it. So see blink without delay!

Mark

holmes4: Of course as you can't check the elapsed time or your sensors when using delay() you need to learn to do without it. So see blink without delay!

Mark

Just had a look at that does it just wait based on a time value you choose? I'm not trying to do that I'm trying to get it to wait until the light level is above 30 before moving

I'm not trying to do that I'm trying to get it to wait until the light level is above 30 before moving

You're code appears to already do that. Please explain the problem again, as I'm missing something.

As I said if you are in a call to delay() no other part of your program does any thing. So for what you want do do you must look at the blink without delay example, and then because you want to combine different thing like a 30's delay but if the LDR value does somthing and something else you need to look at FSM (Finite State Machines) in the playground section of the site. But you should NEVER EVER USE delay(). again look at blink without delay.

Mark

PaulS:

I'm not trying to do that I'm trying to get it to wait until the light level is above 30 before moving

You're code appears to already do that. Please explain the problem again, as I'm missing something.

Sorry it runs correctly when the light level drops and moves in the opposite direction when its above but the problem is it keeps running when its below 30 it just won't stop and I want to make it run for 10 seconds then wait until the light level is above 30 before moving

Huh? I sure cannot understand that long run-on sentence. Maybe the others can.

Please explain CLEARLY:

What you want to have happen. Step by step. Moment by moment.

What works.

What doesn't work.

Thanks!

So, it sounds like you have a limit switch for one direction, but not for the other. Is that right?

Why not start the motor, delay() for 10 seconds, and then stop the motor? I don't understand why you aren't willing to do that.

Or, use the blink without delay philosophy and start the motor running and record when that happened. On a later pass through loop, if the motor is running, and has been running for 10 seconds, turn it off and clear the started time.

vaj4088: Huh? I sure cannot understand that long run-on sentence. Maybe the others can.

Please explain CLEARLY:

What you want to have happen. Step by step. Moment by moment.

What works.

What doesn't work.

Thanks!

Light level above 30 & buttonstate == HIGH Motor moves in direction A until limit switch is pressed and buttonstate goes to LOW Motor waits for light level to go below 30 and buttonstate is LOW Motor moves in direction B for 30 seconds Motor waits for light level to be above 30 before turning on again Motor moves in direction A and process repeats

Thats what I want to happen but the motor won't wait after its moved in direction B it just keeps going. I want it to wait until the light level is above 30 before doing anything at all.

Cheers

PaulS: So, it sounds like you have a limit switch for one direction, but not for the other. Is that right?

Why not start the motor, delay() for 10 seconds, and then stop the motor? I don't understand why you aren't willing to do that.

Or, use the blink without delay philosophy and start the motor running and record when that happened. On a later pass through loop, if the motor is running, and has been running for 10 seconds, turn it off and clear the started time.

I am trying to get it to stop but it won't

These two don’t seem to tie:

  if (sensorValue <= 30 && buttonstate == HIGH)

Light level above 30 & buttonstate == HIGH

wildbill:
These two don’t seem to tie:

  if (sensorValue <= 30 && buttonstate == HIGH)

Light level above 30 & buttonstate == HIGH

Sorry my mistake yeah that should be the other way around

The motor doesn’t stop because on every iteration of loop you do this test:

if (sensorValue <= 30 && buttonstate == HIGH)

and if it’s true, you run the motor.

There’s nothing there to stop it being executed again & again, as you observe.

You could solve this with a boolean variable - MoveInDirectionA perhaps. Test it as well in the if above. In the body of the if, set it to false. Add another if to check whether sensorvalue is greater than 30 - in that instance set the boolean to true.

Your system has a number of states. In each state the behaviour (ie the correct response to various inputs and timeouts) is different.

Thus you need a variable or variables that record the current state explicitly.

So first go and write down the various states, and the relevant inputs or timeouts that cause particular outputs and state changes. This is a state-machine and all non-trivial sketches tend to be written this way because it allows different things to be controlled in (pseudo) parallel.

loop() ends up being a big switch statement dependent on the current state.

wildbill:
The motor doesn’t stop because on every iteration of loop you do this test:

if (sensorValue <= 30 && buttonstate == HIGH)

and if it’s true, you run the motor.

There’s nothing there to stop it being executed again & again, as you observe.

You could solve this with a boolean variable - MoveInDirectionA perhaps. Test it as well in the if above. In the body of the if, set it to false. Add another if to check whether sensorvalue is greater than 30 - in that instance set the boolean to true.

So use a true/false command as well to check to see if the sensor is at the correct level then act accordingly?

So use a true/false command as well to check to see if the sensor is at the correct level then act accordingly?

Yes. Or go the state machine route as suggested earlier.

wildbill:

So use a true/false command as well to check to see if the sensor is at the correct level then act accordingly?

Yes. Or go the state machine route as suggested earlier.

I have no experience with state machines.
Know any good tutorial sites?