Need help using millis()

Ok, so at the moment my front sensors on my robot are checking if an object is 12" in front and if not then proceeding with program. My problem is the sensors wont check again until the code has ran thru and loops back to the top, I've tried to implement millis() to check if 1 second has passed and then to check sensors again, WHILE the rest of the code is running. But it isnt working. If someone could give me a little help on what I'm doing wrong that would be great thank you. To sum up, I'm wanting the sensors to continue checking for an object in front while the rest of the code is running, instead of waiting for the program to loop back to the top and start over. (This code is not complete and I'm a beginner to programming and robotics, just fyi! lol)

//ARC Test Code2

#include <SoftwareSerial.h>    //Include Serial Library
#define Rx 4         //Sabertooth Motor Controller2 Recieve Pin
#define Tx 5         //Sabertooth Motor Controller2 Transmit Pin
#define rxPin 2      //Sabertooth Motor Controller1 Recieve Pin
#define txPin 3      //Sabertooth Motor Controller1 Transmit Pin
#define M1_for 127   //Sabertooth Motor 1 (left) Forward
#define M1_stop 64   //Sabertooth Motor 1 (left) Stop
#define M1_rev 1     //Sabertooth Motor 1 (left) Reverse
#define M2_for 255   //Sabertooth Motor 2 (right) Forward
#define M2_stop 192  //Sabertooth Motor 2 (right) Stop
#define M2_rev 128   //Sabertooth Motor 2 (right) Reverse
#define M3_start 127 //Sabertooth Motor 3 (blade) On
#define M3_stop 64   //Sabertooth Motor 3 (blade) Off

SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
SoftwareSerial mySerial2 = SoftwareSerial(Rx, Tx);

//name digital input & output pins
#define BUTTON 7     //Start Button Pin
#define Echo 11      //Ultrasonic Sensor Pin In
#define Trig 10      //Ultrasonic Sensor Pin Out

long pwmRange, inch; //Declare values for Ultrasonic Sensor

unsigned long changeTime;//Declaring sensor changeTime
int sensorDelay(1000);//Time between running sensor function

int val = 0;         //val stores the state of the input pin
int old_val = 0;     //stores the previous value of "val"
int state = 0;       //0 = motor off and 1 = motor on

void setup() {
  Serial.begin(9600);       //Begin Serial at 9600 baud rate
  pinMode(rxPin, INPUT);    //Set rxPin as an Input
  pinMode(txPin, OUTPUT);   //Set txPin as an Output
  pinMode(Rx, INPUT);       //Set Rx as an Input
  pinMode(Tx, OUTPUT);      //Set Tx as an Output
  mySerial.begin(9600);     //Begin mySerial at 9600 baud rate
  mySerial2.begin(9600);    //Begin mySerial2 at 9600 baud rate
  pinMode(BUTTON, INPUT);   //Set BUTTON as an Input
  pinMode(Echo, INPUT);     //Set Echo as an Input
  pinMode(Trig, OUTPUT);    //Set Trig as an Output
  
  changeTime = millis();    //Sensor clock
}

void loop(){
  val = digitalRead(BUTTON);     //Check if BUTTON was pushed       
  if ((val == HIGH) && (old_val == LOW)){
    state = 1 - state;
    delay(20);
  }
  old_val = val;           //val is now old, store it
  if (state == 1) {        //If BUTTON was pushed start program
  
   if ((millis() - changeTime) > sensorDelay){//check if 1 sec has passed
    frontSensor();         //Function for front sensors
    changeTime = millis(); //
  }
  if (inch < 12){              //Check if object is within 12"
    mySerial.write(M1_stop);   //Stop motor1
    mySerial.write(M2_stop);   //Stop motor2
  }
  if (inch > 12){              //Check if object is farther than 12"
    for (int x=0; x<3; x++){
     mySerial.write(M1_for);
     delay(2000);
     mySerial.write(M1_rev);
     delay(2000);
     mySerial.write(M1_stop);
    }
    for (int x=0; x<3; x++){
      mySerial.write(M2_for);
      delay(2000);
      mySerial.write(M2_rev);
      delay(2000);
      mySerial.write(M2_stop);
    }
 }
}
}
void frontSensor(){           //Function for front sensors
  digitalWrite(Trig, LOW);
  delay(2);
  digitalWrite(Trig, HIGH);
  delay(10);
  digitalWrite(Trig, LOW);
  pwmRange = pulseIn(Echo, HIGH);
  
  inch = pwmRange / 147;   
  delay(200);
}

Mixing millis() and delay() is a recipe for disaster. Get rid of all the calls to delay(). It is time to read the sensor, or not (though why you don't read it every pass through loop() is a mystery). It is time to move forward, or not. It is time to stop, or not.

You don't walk down the hall with your eyes closed, do you? Open your eyes. See how far the end of the hall is, and close your eyes and walk for two seconds. You'd be bruised and bloody all the time. Why is your robot doing that?

Why is there a delay() after reading the distance sensor? That bit makes no sense.

Yea the delay() after reading the sensor can come out, It was there originally to read the sensor every 200ms, but now that my code has progressed I dont need it anymore. The other delays() tell the motors how long to stay on and how long to stay off. To move my robot forward, turn him, and so forth. I suppose using encoders on my wheels would tell my robot how FAR to go forward, instead of relying on delay() function to tell him how LONG to go forward would prolly work better...but dont have the encoders atm of the know how of how to use them lol, more learning in the future! So is there a way to get him to check his sensors every (say) second while the rest of the program runs? Or will he only do it every time the programs loops?

Ok Paul, I had a thot, would I be better off to use millis() to run the motors instead of delay()? Like if I wanted my robot to move forward for 5 seconds, I could have it check if motor1 and motor 2 are off, turn them on and check if its been => 5 seconds since they came on and if so, turn them off? I could do the same to run one motor to turn left or right...? A little more complicated but that would get rid of the delays right? And the whole program would loop faster so my sensors would check everytime it looped...

would I be better off to use millis() to run the motors instead of delay()?

Yes, but that is still not necessarily the ideal way. What is the robot supposed to do? Move forward a fixed distance, and turn? Or is it supposed to go until it encounters an obstacle?

Yes, move forward a fixed distance and turn.

More specifically, move forward fixed distance, turn left or right 180 degrees, move forward again a fixed distance, repeat again and again pathing back and forth across my yard, and stopping if something or someone gets in its path.

Reply #3 - now you're catching on!

"would I be better off to use millis() to run the motors instead of delay()?"

Its not really more complicated - just add a couple of 'flags' to keep track of what you're doing.
Like

if ((motorRunningFlag == 1) &&( ( currentTime-previousTime) >= motorOntime ) { //if motor is running & time has passed turn it off
"turn off the motor";
motorRunningFlag == 0;
previousTime = currentTime;
}
if ((motorRunningFlag == 0) &&( ( currentTime-previousTime) >= motorOfftime ) { //if motor is Not running & time has passed turn it on
"turn on the motor";
motorRunningFlag == 1;
previousTime = currentTime;
}

Ok, thanks Crossroads, that helps. I was going thru my 2 books trying to figure out how to set that up, havent worked with millis() before. Heres my new test code, I haven't tried to verify it yet as i have some questions in declaring the functions. motorRunningflag would be an "int" right? and previousTime would be a "long"? or "unsigned long"? And I'm not sure about currentTime...would that be a "long" as well? or would it be like millis() = currentTime? motorOntime and motorOfftime I just declared as "long" with 5000ms timer (thats a random time, I'll put the currect time in when I figure out how long they will actually run and be off and so forth, once its in the yard moving around lol).

//ARC Test Code2

#include <SoftwareSerial.h>    //Include Serial Library
#define Rx 4         //Sabertooth Motor Controller2 Recieve Pin
#define Tx 5         //Sabertooth Motor Controller2 Transmit Pin
#define rxPin 2      //Sabertooth Motor Controller1 Recieve Pin
#define txPin 3      //Sabertooth Motor Controller1 Transmit Pin
#define M1_for 127   //Sabertooth Motor 1 (left) Forward
#define M1_stop 64   //Sabertooth Motor 1 (left) Stop
#define M1_rev 1     //Sabertooth Motor 1 (left) Reverse
#define M2_for 255   //Sabertooth Motor 2 (right) Forward
#define M2_stop 192  //Sabertooth Motor 2 (right) Stop
#define M2_rev 128   //Sabertooth Motor 2 (right) Reverse
#define M3_start 127 //Sabertooth Motor 3 (blade) On
#define M3_stop 64   //Sabertooth Motor 3 (blade) Off

SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
SoftwareSerial mySerial2 = SoftwareSerial(Rx, Tx);

//name digital input & output pins
#define BUTTON 7     //Start Button Pin
#define Echo 11      //Ultrasonic Sensor Pin In
#define Trig 10      //Ultrasonic Sensor Pin Out


[glow=yellow,2,300]long previousTime = 0;   //Store last time motor ran
long motorOntime = 5000; //Time motor will on
long motorOfftime = 5000;//Time motor is off
int motorRunningflag = 0;//0 = motor is off, 1 = motor is on[/glow]

long pwmRange, inch; //Declare values for Ultrasonic Sensor

int val = 0;         //val stores the state of the input pin
int old_val = 0;     //stores the previous value of "val"
int state = 0;       //0 = dont run program, 1 = run program

void setup() {
  Serial.begin(9600);       //Begin Serial at 9600 baud rate
  pinMode(rxPin, INPUT);    //Set rxPin as an Input
  pinMode(txPin, OUTPUT);   //Set txPin as an Output
  pinMode(Rx, INPUT);       //Set Rx as an Input
  pinMode(Tx, OUTPUT);      //Set Tx as an Output
  mySerial.begin(9600);     //Begin mySerial at 9600 baud rate
  mySerial2.begin(9600);    //Begin mySerial2 at 9600 baud rate
  pinMode(BUTTON, INPUT);   //Set BUTTON as an Input
  pinMode(Echo, INPUT);     //Set Echo as an Input
  pinMode(Trig, OUTPUT);    //Set Trig as an Output
}

void loop(){
  val = digitalRead(BUTTON);     //Check if BUTTON was pushed       
  if ((val == HIGH) && (old_val == LOW)){
    state = 1 - state;
    delay(20);
  }
  old_val = val;           //val is now old, store it
  if (state == 1) {        //If BUTTON was pushed start program
    frontSensor();         //Function for front sensors
  }
  if (inch < 12){              //Check if object is within 12"
    mySerial.write(M1_stop);   //Stop motor1
    mySerial.write(M2_stop);   //Stop motor2
  }
  if (inch > 12){              //Check if object is farther than 12"
    if ((motorRunningflag == 0) && (currentTime - previousTime) >= motorOntime){
      mySerial.write(M1_for);
      mySerial.write(M2_for);
      motorRunningflag == 1;
      previousTime = currentTime;
    }
    if ((motorRunningflag == 1) && (currentTime - previousTime) >= motorOfftime){
      mySerial.write(M1_stop);
      mySerial.write(M2_stop);
      motorRunningflag == 0;
      previousTime = currentTime;
    }
   }
  }


void frontSensor(){           //Function for front sensors
  digitalWrite(Trig, LOW);
  delay(2);
  digitalWrite(Trig, HIGH);
  delay(10);
  digitalWrite(Trig, LOW);
  pwmRange = pulseIn(Echo, HIGH);
  
  inch = pwmRange / 147;   
  Serial.print(inch);
  Serial.print(" inches");
}

Opps, I tried to hi-light some of the code but it didnt work...Heres what its suppose to look like...

long previousTime = 0;   //Store last time motor ran
long motorOntime = 5000; //Time motor will on
long motorOfftime = 5000;//Time motor is off
int motorRunningflag = 0;//0 = motor is off, 1 = motor is on
motorRunningflag == 1;

You probably meant an assignment and not a comparison.

I use "unsigned long" for anything I do with time, so only dealing with positive numbers.

"Long variables are extended size variables for number storage, and store 32 bits (4 bytes), from -2,147,483,648 to 2,147,483,647. "

"millis() Returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days.

Number of milliseconds since the program started (unsigned long) "

I use byte for the flags, the smallest data type available, but int will work as well.

Setting the flags, yeah those should have been single ='s, not doubles. Got a little carried away I guess pounding out that code!

So...something like this?

unsigned long currentTime = 0;    //Current clock time
unsigned long previousTime = 0;   //Store last time motor ran
unsigned long motorOntime = 5000; //Time motor will on
unsigned long motorOfftime = 5000;//Time motor is off
int motorRunningflag = 0;         //0 = motor is off, 1 = motor is on

Should millis() be in there somewhere?

jamos82:
So...something like this?

unsigned long currentTime = 0;    //Current clock time

unsigned long previousTime = 0;   //Store last time motor ran
unsigned long motorOntime = 5000; //Time motor will on
unsigned long motorOfftime = 5000;//Time motor is off
int motorRunningflag = 0;         //0 = motor is off, 1 = motor is on




Should millis() be in there somewhere?

In that section of code? Do you need a clock to tell you how long to cook a turkey?

Nope, add
currentTime = millis();
at the start of loop to capture the current time every pass thru.

Ah ok, thx alot for all this Crossroads. Ill implement that tomorrow and see if I can get it to work.