Go Down

### Topic: Maze solver "stop" method? (Read 1 time)previous topic - next topic

#### OllyR

##### Sep 04, 2012, 11:26 pm
Im upgrading my line follower (which rocks) to a maze solver. We have white floorboards here, so with a big roll of electrical tape i can make a pretty cool maze in the spare room. Im currently looking for ideas on how to make a "finish" for the maze. My two ideas are currently:

Count the distance across a box, ie: stop after x ms of no returned signals.

Or

Make the box a colour, and use an rgb sensor to detect the box. The problem here is i have run out of pins!

So assuming the count plan is a good idea, any suggestions as to how to say "if x &y&z are all low for more than x ms...", or at least the waiting part...

#### PeterH

#1
##### Sep 05, 2012, 01:35 am
How about putting an obstacle just past the exit that trips a physical switch mounted on the front? So the 'bot's goal would be to run into something without crossing a line.
I only provide help via the forum - please do not contact me for private consultancy.

#### PaulS

#2
##### Sep 05, 2012, 12:59 pm
Quote
any suggestions as to how to say "if x &y&z are all low for more than x ms...",

You need to periodically check all values. If all are low, set the time that they went low (or, more accurately, the time they were detected to be low). If any goes high later, clear the time.

Periodically, see if the difference between now and then is greater than the interval of interest, when then is not 0. If so, stop.

#### OllyR

#3
##### Sep 05, 2012, 10:44 pm
I'm struggling a bit here. Ive found the millis() function, bit not sure how to "call" it, and make any decisions based on it.
Can i reset the millis clock to zero with each change of state perhaps? Or is that not the way to go about it
I think i want it to run for 1 sec over all high, just to allow it to cross junctions, and account for flaws in my white floorboards.
Also to stop after 5 secs of white, and assume its lost..

Little help?

#### PeterH

#4
##### Sep 05, 2012, 11:24 pm
You call it by putting the function name in your code followed by brackets:

Code: [Select]
`unsigned long now = millis();`

I suggest you look at the 'blink without delay' example sketch to see how you would use this to do things when a given time has passed.
I only provide help via the forum - please do not contact me for private consultancy.

#### OllyR

#5
##### Sep 06, 2012, 12:56 amLast Edit: Sep 06, 2012, 01:04 am by OllyR Reason: 1
So what i tried is this:

1: Create a "long" for "last known event" (last)
2: created a "long" for the delay (interval) although im not sure why i cant just refer to "2000" in the code where required, but that is how the blink tutorial did it so fine.

3: in the line following arguments, (for 000, 001, 010, 011, 100, 110) i have asked it to assign "last" with the current time. I HOPE this will update the "last" value every state change.

4: finally for argument 111:

Code: [Select]
`if now - last < interval { carry  on!}if now - last > interval {all stop!}` (I would like this to declare the end to the code, but it isn't necessary, as once it has stopped, it wont be changing states on the sensors.

i have enclosed this last section between two lines of asterixes ************************** near the bottom of the sketch.

in practice as soon as the argument 111 is reached, it stops.
i want it to carry on for 2000 ms, and then if the argument is not changed within the 2000 ms, THEN stop.

if anyone could point out what ive missed it would be greatly appreciated.

Thanks all, sorry if im being thick.

Code: [Select]
`#include <AFMotor.h>AF_DCMotor motorL(3, MOTOR12_1KHZ);  AF_DCMotor motorR(2, MOTOR12_1KHZ);// These constants won't change:const int LeftPR = A1;    // pin that the sensor is attached toconst int CentrePR = A2;    // pin that the sensor is attached toconst int RightPR = A3;    // pin that the sensor is attached toconst int IndicatorL = 10;        // pin that the LED is attached toconst int IndicatorC = 9;        // pin that the LED is attached toconst int IndicatorR = 19;        // pin that the LED is attached toconst int button = 18;// finish line timinglong last= 0;long interval = 2000; // delay time// variables:int LeftValue = 0;         // the sensor valueint LeftMin = 1023;        // minimum sensor valueint LeftMax = 0;           // maximum sensor valueint CentreValue = 0;         // the sensor valueint CentreMin = 1023;        // minimum sensor valueint CentreMax = 0;           // maximum sensor valueint RightValue = 0;         // the sensor valueint RightMin = 1023;        // minimum sensor valueint RightMax = 0;           // maximum sensor valuevoid setup() {  // Serial monitor  Serial.begin(9600);           // set up Serial library at 9600 bps  //Motors  //set the speed to 200 of 255 of "motorL".  //Note that 0 is stop, 255 is full speed:  motorL.setSpeed(200);      // set the speed to 200 of 255 of "motorR":  motorR.setSpeed(200);  //Calibraton  // turn on LEDs to signal the start of the calibration period:  pinMode(IndicatorL,OUTPUT);  pinMode(IndicatorC,OUTPUT);  pinMode(IndicatorR,OUTPUT);  digitalWrite(IndicatorL, HIGH);  digitalWrite(IndicatorC, HIGH);  digitalWrite(IndicatorR, HIGH);  // calibrate during the first 5 seconds  {      while (millis() < 5000) {      //Spin on the spot      motorL.run(FORWARD);      // turn it on going forward      motorR.run(BACKWARD);  // motor 2 goes forward as well      //Calibrate      LeftValue = analogRead(LeftPR);      // record the maximum sensor value      if (LeftValue > LeftMax) {        LeftMax = LeftValue;      }      // record the minimum sensor value      if (LeftValue < LeftMin) {        LeftMin = LeftValue;      }      CentreValue = analogRead(CentrePR);      // record the maximum sensor value      if (CentreValue > CentreMax) {        CentreMax = CentreValue;      }      // record the minimum sensor value      if (CentreValue < CentreMin) {        CentreMin = CentreValue;      }      RightValue = analogRead(RightPR);      // record the maximum sensor value      if (RightValue > RightMax) {        RightMax = RightValue;      }      // record the minimum sensor value      if (RightValue < RightMin) {        RightMin = RightValue;      }    }    motorL.run(RELEASE);      // turn it on going forward    motorR.run(RELEASE);  // motor 2 goes forward as well    // signal the end of the calibration period    digitalWrite(IndicatorL, LOW);    digitalWrite(IndicatorC, LOW);    digitalWrite(IndicatorR, LOW);    delay(1000);    digitalWrite(IndicatorC, HIGH);    delay(100);    digitalWrite(IndicatorC, LOW);    delay(100);    digitalWrite(IndicatorC, HIGH);    delay(100);    digitalWrite(IndicatorC, LOW);    delay(100);    digitalWrite(IndicatorC, HIGH);    delay(100);    digitalWrite(IndicatorL, LOW);    digitalWrite(IndicatorC, LOW);    digitalWrite(IndicatorR, LOW);  }  //hold  while (digitalRead (button) == HIGH){    // stops script. Its waiting for a button press (LOW on "button")  }}void loop() {  {    //LEFT SENSOR    LeftValue = analogRead(LeftPR);    // apply the calibration to the sensor reading    LeftValue = map(LeftValue, LeftMin, LeftMax, 0, 100);    LeftValue = constrain(LeftValue, 0, 200);    // in case the sensor value is outside the range seen during calibration    if (LeftValue > 100) {      digitalWrite (IndicatorL, HIGH);    }    if (LeftValue < 100) {      digitalWrite (IndicatorL, LOW);    }    //CENTRE SENSOR    CentreValue = analogRead(CentrePR);    // apply the calibration to the sensor reading    CentreValue = map(CentreValue, CentreMin, CentreMax, 0, 100);    CentreValue = constrain(CentreValue, 0, 200);    // in case the sensor value is outside the range seen during calibration    if (CentreValue > 100) {      digitalWrite (IndicatorC, HIGH);    }    if (CentreValue < 100) {      digitalWrite (IndicatorC, LOW);    }    // RIGHT SENSOR    RightValue = analogRead(RightPR);    // apply the calibration to the sensor reading    RightValue = map(RightValue, RightMin, RightMax, 0, 100);    RightValue = constrain(RightValue, 0, 200);    // in case the sensor value is outside the range seen during calibration    if (RightValue > 100) {      digitalWrite (IndicatorR, HIGH);    }    if (RightValue < 100) {      digitalWrite (IndicatorR, LOW);    }  }  // Line following arguments  // Forward 010, 000 (000 to be set to 5 second time limit once ive worked out how to handle millis)  if ((digitalRead(IndicatorL) == LOW && digitalRead(IndicatorC) == LOW && digitalRead(IndicatorR) == LOW)||    (digitalRead(IndicatorL) == LOW && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == LOW)){    motorL.run(FORWARD);      motorR.run(FORWARD);      unsigned long last = millis();  }  //Turn right: 001, 011  if ((digitalRead(IndicatorL) == LOW && digitalRead(IndicatorC) == LOW && digitalRead(IndicatorR) == HIGH)||    (digitalRead(IndicatorL) == LOW && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == HIGH)){    motorL.run(FORWARD);      motorR.run(RELEASE);      unsigned long last = millis();  }  //Turn Left: 100, 110  if ((digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == LOW && digitalRead(IndicatorR) == LOW)||    (digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == LOW)){    motorL.run(RELEASE);        motorR.run(FORWARD);    unsigned long last = millis();  }  // finish box or cross roads decision **************************************  unsigned long now = millis();  if (digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == HIGH && (now - last < interval)){    motorL.run(FORWARD);      motorR.run(FORWARD);  }  else  if (digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == HIGH && (now - last > interval))  {    motorL.run(RELEASE);      motorR.run(RELEASE);    }  //***********************************************  Serial.print("Left:");  Serial.print(LeftValue);  Serial.print(" Centre:");  Serial.print(CentreValue);  Serial.print(" Right:");  Serial.print(RightValue);  Serial.println();}`

#### PeterH

#6
##### Sep 06, 2012, 01:43 am
Code: [Select]
`long last= 0;long interval = 2000; // delay time`

These need to be unsigned long not just long.

There are several places where you put this line in your code:

Code: [Select]
`    unsigned long last = millis();`
I assume the intent is to update the global variable. Because you included the type in this statement, it actually declares a new local variable within that block of code, which is updated with the return value from millis() and them immediately thrown away as you leave that code block.

If you want to update a variable which has already been declared, you would need to change that code to:

Code: [Select]
`    last = millis();`

Code: [Select]
`  if (digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == HIGH && (now - last < interval)){    motorL.run(FORWARD);      motorR.run(FORWARD);  }  else  if (digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == HIGH && (now - last > interval))  {    motorL.run(RELEASE);      motorR.run(RELEASE);    }`
These conditions can be written more concisely:
Code: [Select]
`  if (digitalRead(IndicatorL) == HIGH && digitalRead(IndicatorC) == HIGH && digitalRead(IndicatorR) == HIGH){    if(millis() - last < interval)    {        // timeout has not expired, keep going        motorL.run(FORWARD);          motorR.run(FORWARD);    }    else    {        // timeout has expired, assume we have reached the end        motorL.run(RELEASE);          motorR.run(RELEASE);      }}`
I only provide help via the forum - please do not contact me for private consultancy.

#### OllyR

#7
##### Sep 07, 2012, 09:12 pm
Thats got it!

thanks for your help guys, its really appreciated.
funny how these things are easy when you know how, and its the details that make the difference.

#### GoldStar611

#8
##### Sep 08, 2012, 12:33 am
Don't forget to handle the case where millis() rolls back over to 0 just like an odometer in a car. That is sure to throw you for a loop down the road

#### PeterH

#9
##### Sep 08, 2012, 02:08 am

Don't forget to handle the case where millis() rolls back over to 0 just like an odometer in a car. That is sure to throw you for a loop down the road

If you code it properly as shown in the code fragment I posted, the rollover behaves correctly. If you find you need to explicitly deal with the rollover case, you're doing it wrong.
I only provide help via the forum - please do not contact me for private consultancy.

Go Up

Please enter a valid email to subscribe