millis() to stop motor

This sketch runs a motor random speed/random direction but the function (stopMotor) and every other attempt to stop the motor has failed. What am I doing wrong?

int randNumberSpeed; // variable to store the random speed value
int randNumberDir;  // variable to store the random direction value 
int motorSpeed = 11; // motor speed
int motorDir = 12; // motor direction
unsigned long time;

void setup() 
{
//time = millis();  
Serial.begin(9600);
randomSeed(millis());
pinMode(motorSpeed,OUTPUT);
pinMode(motorDir,OUTPUT);

} 

void loop()
{
    
randomSeed(millis()); // sets millis() as seed

randNumberDir = random(255); // random number from 0-255
analogWrite(motorDir, randNumberDir); // outputs PWM signal
delay(500); // pauses for half a second


randNumberSpeed = random(255); // random number from 0-255
analogWrite(motorSpeed, randNumberSpeed); // outputs PWM signal
delay(500); // pauses for half a second
motorStop();

}

void motorStop(){
  
  
 if(millis() - time  > 3000) {
   digitalWrite(motorDir,LOW);
   digitalWrite(motorSpeed,LOW);

 time = millis();
}
}

The randomSeed function should be called once. From then on, the numbers generated by the random function will be, well, random.

At the end of each pass through loop, you call motorStop. The first time though, time has not been explicitly initialized. So, it might be 0, or it might be any number. It's probably 0, but it it never safe to assume that it is.

So, you check that now (what millis() returns) minus 0 to see if is is greater than 3000. If you run this sketch right after uploading it, you will only have been running for a little over a second (2 500 millisecond delays in loop), so millis() - time will be less than 3000, so the block of code to turn the motor off will be skipped.

Then, you set time to NOW, and return. The loop function is run again, which takes another second. So now minus then will be just over 1000, so the motor is not turned off.

And around and around we go.

When do you want to turn the motor off?

I want to turn the motor off after it runs from 3 ~ fives seconds. This, and the counter motor you helped me with, are for a sculpture involving a number of motors, some random and others using count. I am using a Solarbotics L298 board http://www.solarbotics.com/products/k_cmd/

MotorDir and MotorSpeed are pos/neg of the motor are connected to the two output terminals.

Please disregard the last post. MotorDir/motorSpeed are connected to the driver board inputs.

So, in setup(), you want to uncomment the time = millis() statement.

Then, remove the time = millis() statement from motorStop.

When setup runs, time gets a value (of approximately 0). Loop runs, and motorStop gets called. Only 1000 milliseconds (approximately) has elapsed, so the motor stays running. Loop gets called again, as well as motorStop. Now, approximately 2000 milliseconds has gone by, so the motor keeps running. On the next pass, it should stop.

As you probably have guessed, using millis as a timer to turn off the motor is giving me some serious angst! Learning the procedure is fundamental to this and other pieces I hope to build so possibly eliminating all but the necessary hardware will be helpful. I have taken the "blink without delay" example and adapted, or corrupted it, to turn an LED off after three seconds. I seem to be making the same mistake here as the motor sketch. I don't want to blink the led, I want it to stop altogether after three seconds.

const int ledPin =  13;         // the number of the LED pin

long previousMillis = 0;        // will store last time LED was updated
long interval = 3000;           // the led turns off after 3 seconds)

void setup() {
 pinMode(ledPin, OUTPUT);
Serial.begin(9600); 
}

void loop()
{

  if (millis() - previousMillis > interval) {
    digitalWrite(ledPin,LOW);
    previousMillis = millis();   
   
  }
     Serial.println(previousMillis);
}

Well, this seems to time an led off. Now, to make the random motor do the same.

const int ledPin =  13;         // the number of the LED pin

long previousMillis = 0;        // will store last time LED was updated
long interval = 5000;           // the led turns off after 3 seconds)

void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600); 
digitalWrite(ledPin,HIGH);
}

void loop()
{

  if (millis() - previousMillis > interval) {
    digitalWrite(ledPin,LOW);
    previousMillis = millis();   
   
  }
     Serial.println(previousMillis);
     delay(1000);
}

But, the same method won't stop the motor:

int randNumberSpeed; // variable to store the random speed value
int randNumberDir;  // variable to store the random direction value
int motorSpeed = 11; // motor speed
int motorDir = 12; // motor direction
long previousMillis =0;
long interval = 5000;
int enable = 8;

void setup()
{

Serial.begin(9600);
randomSeed(millis());
pinMode(motorSpeed,OUTPUT);
pinMode(motorDir,OUTPUT);
digitalWrite(motorSpeed,HIGH);
digitalWrite(motorDir,HIGH);
digitalWrite(enable,HIGH);

}

void loop()
{


randNumberDir = random(255); // random number from 0-255
analogWrite(motorDir, randNumberDir); // outputs PWM signal
delay(500); // pauses for half a second


randNumberSpeed = random(255); // random number from 0-255
analogWrite(motorSpeed, randNumberSpeed); // outputs PWM signal
delay(500); // pauses for half a second
motorStop();

}

void motorStop(){


 if(millis() - previousMillis  > interval) {
   digitalWrite(motorDir,LOW);
   digitalWrite(motorSpeed,LOW);
   digitalWrite(enable,LOW);
   previousMillis = millis();


}
delay(1000);
}

You want the motor to stop after a pre-defined interval, right?

Then, stop moving the start of the interval, and eventually you'll get to the end of the interval!

previousMillis = millis();

The previousMillis variable contains the start of the interval. You keep resetting it if you aren't at the end of the interval. All that that does is assure that you will never get there.

And, that's the problem you're having, right?

This sketch seems to do the trick, at 2:00am! With more experience, I hope to become articulate enough to describe the goal in terms that focus on the problem instead of confusing those who are coaching me. Every wild goose chase has turned up more than a few ducks that have proven to be valuable steps in learning Arduino code. I have to activate the motor with a motion sensor and include opto switches, so still have a way to go but, thanks to you folks, I am a little more knowledgeable. Thanks again.

int randNumberSpeed; // variable to store the random speed value
int randNumberDir;  // variable to store the random direction value
int motorSpeed = 11; // motor speed
int motorDir = 12; // motor direction


void setup()
{

Serial.begin(9600);
randomSeed(millis());
pinMode(motorSpeed,OUTPUT);
pinMode(motorDir,OUTPUT);


}

void loop()
{
if (millis() < 10000){
//randomSeed(millis()); // sets millis() as seed

randNumberDir = random(255); // random number from 0-255
analogWrite(motorDir, randNumberDir); // outputs PWM signal
delay(500); // pauses for half a second


randNumberSpeed = random(255); // random number from 0-255
analogWrite(motorSpeed, randNumberSpeed); // outputs PWM signal
delay(500); // pauses for half a second
//motorStop();
}
else{
  
  digitalWrite(motorSpeed,LOW);
  digitalWrite(motorDir,LOW);

}

}

The two sketches, timer and PIR, work in separate sketches, but not in this sketch. I have tried plugging in the “motor” function in many locations with no results; the ledPin lights the LED but the motor is still low. I don’t know how to combine the two functions.

int randNumberSpeed; // variable to store the random speed value
int randNumberDir;  // variable to store the random direction value
int motorSpeed = 11; // motor speed
int motorDir = 12; // motor direction
/*----------------------------------------------------------------*/

long unsigned int lowIn; 
int calibrationTime = 30;
long unsigned int pause = 5000;  
boolean lockLow = true;
boolean takeLowTime;  
int pirPin = 4;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;
/*---------------------------------------------------------------*/
void setup()
{
//time = millis();
Serial.begin(9600);
randomSeed(millis());
pinMode(motorSpeed,OUTPUT);
pinMode(motorDir,OUTPUT);
/*--------------------------------------------------------------*/
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);
 //give the sensor some time to calibrate
  for(int i = 0; i < calibrationTime; i++){
      delay(1000);
  }    
     
  }
/*--------------------------------------------------------------*/
void loop()
{
  if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
       if(lockLow){  
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;            
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         delay(50);
         }         
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){       
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
          // motor();
      
       }
       motor();
     }
}
/*--------------------------------------------------------------*/

void motor(){


if (millis() < 10000){
//randomSeed(millis()); // sets millis() as seed

randNumberDir = random(255); // random number from 0-255
analogWrite(motorDir, randNumberDir); // outputs PWM signal
delay(500); // pauses for half a second


randNumberSpeed = random(255); // random number from 0-255
analogWrite(motorSpeed, randNumberSpeed); // outputs PWM signal
delay(500); // pauses for half a second
//motorStop();
}
else{
  
  digitalWrite(motorSpeed,LOW);
  digitalWrite(motorDir,LOW);

}

}
if (millis() < 10000){

This will only work in the first 10 seconds after reset - is that what you intended?

randNumberDir = random(255); // random number from 0-[glow]254[/glow]

Yes, when the PIR pin goes high, I want the motor to run random direction/speed for ten seconds. Tested separately, the motor will run in a spasmodic way that will work for the application. I need the PIR to activate the process when a viewer approaches.

No. I think you misunderstood me. The "millis" clock is reset to zero when the processor is reset, so it can only be less than 10000 in the first ten seconds from when you last reset the processor.

Hmm. I am sure that is a relevant question and, yes, I didn't/don't understand. Sorry to ask, but would you please restate your question in words even an elementary art teacher can grasp? Thanks for the help.

After reading your post a dozen times, I think you are making it clear that, given “<” 10000 will insure the motor never kicks in? Since the motor sketch, by itself, behaves as it should, then is there something in the code above (the PIR) that disables the “motor” function?

Every time you call “millis”, it returns the number of milliseconds that have elapsed since you reset the processor (give or take a few milliseconds).
So, for example, if you call “millis” after 5 seconds from when your sketch started, it will return a value around 5000.

So, this condition:

if (millis() < 10000){

is only true in the first ten seconds after your sketch started, and so the code after it

//randomSeed(millis()); // sets millis() as seed

randNumberDir = random(255); // random number from 0-255
analogWrite(motorDir, randNumberDir); // outputs PWM signal
delay(500); // pauses for half a second


randNumberSpeed = random(255); // random number from 0-255
analogWrite(motorSpeed, randNumberSpeed); // outputs PWM signal
delay(500); // pauses for half a second
//motorStop();
}

can only ever be executed in the first ten seconds after your sketch started.
After this time, this

else{

  digitalWrite(motorSpeed,LOW);
  digitalWrite(motorDir,LOW);

}

is all that will ever be executed.

The "if(millis < 10000) is commented out here but the motor still doesn’t respond to the PIR. Does this help explain anything?

int randNumberSpeed; // variable to store the random speed value
int randNumberDir;  // variable to store the random direction value
int motorSpeed = 11; // motor speed
int motorDir = 12; // motor direction
/*----------------------------------------------------------------*/

long unsigned int lowIn; 
int calibrationTime = 30;
long unsigned int pause = 5000;  
boolean lockLow = true;
boolean takeLowTime;  
int pirPin = 4;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;
/*---------------------------------------------------------------*/
void setup()
{
//time = millis();
Serial.begin(9600);
randomSeed(millis());
pinMode(motorSpeed,OUTPUT);
pinMode(motorDir,OUTPUT);
/*--------------------------------------------------------------*/
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);
 //give the sensor some time to calibrate
  for(int i = 0; i < calibrationTime; i++){
      delay(1000);
  }    
     
  }
/*--------------------------------------------------------------*/
void loop()
{
  //motor();
  if(digitalRead(pirPin) == HIGH){
        //motor();
       digitalWrite(ledPin, HIGH);
       //the led visualizes the sensors output pin state
       // motor();
       if(lockLow){  
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;            
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         delay(50);
         }         
         takeLowTime = true;
        
       }

     if(digitalRead(pirPin) == LOW){       
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
          //motor();
      
       }
      // motor();
     }
    // motor();
}
/*--------------------------------------------------------------*/

void motor(){


//if (millis() > 10000){
//randomSeed(millis()); // sets millis() as seed

randNumberDir = random(255); // random number from 0-255
analogWrite(motorDir, randNumberDir); // outputs PWM signal
delay(500); // pauses for half a second


randNumberSpeed = random(255); // random number from 0-255
analogWrite(motorSpeed, randNumberSpeed); // outputs PWM signal
delay(500); // pauses for half a second
//motorStop();
}
//else{
  
//  digitalWrite(motorSpeed,LOW);
//  digitalWrite(motorDir,LOW);

//}

//}

What AWOL is alluding to is that the millis() < 10000 statement should look more like

if(millis() - lastMotion < 10000)

where lastMotion is a long that gets set whenever the PIR says that motion has occurred. That way, the motor will run for 10 seconds every time the PIR goes off, which is more like what you want to do.