Shop OBEX P1 Docs P2 Docs Learn Events
Light following and collision detection combination — Parallax Forums

Light following and collision detection combination

ltmhallltmhall Posts: 102
edited 2007-03-19 15:43 in BASIC Stamp

···I’m designing a robot that will roam towards a light source placed in front of it. It will also be
designed to maneuver around objects in its path using collision detection. The light circuit will
consist of three photo-resistor’s (photo-resistors in parallel with 0.01ufd capacitors)·placed on
the front side of the robot (currently I only have two on the robot, but I plan on adding a third).
·
··············· ·\······· /·······
············· 45 \ 90 / 45······

············
···· Top view showing angles of how the photo-resistors will be·positioned on the robot.
··············· ·top view·······
·
· The problem I have is deciding how to maneuver the robot when the photo-resistors don’t sense
the light source. For instance, if the robot senses the light and moves towards it. Along the way the
robot collides into an object and the left micro-switches is pressed. The robot will move backwards
and then turn left (the left turn is 90 degrees for my robot). Afterwards, the robot is now positioned
away from the light source and their in lies the problem. I tried having the robot stop, make 90 degree
turn and then take a measurement and then see if there is light, and it seemed to work when the robot
was within 3 ft of the light source. However, when the robot was further away it wouldn’t sense the light
and all it would do is turn in circles.

·* Any help would be appreciated !
·
·
' {$STAMP BS2}········································ ·' Stamp directive.
' {$PBASIC 2.5}·········································· ' PBASIC directive
LeftAmbient CON 120
RightAmbient CON 122
LeftBright CON 10
RightBright CON 10
' Average Scale factor
LeftThreshold CON LeftBright + LeftAmbient / 2 * 5 / 8
RightThreshold CON RightBright + RightAmbient / 2 * 5 / 8
'
[noparse][[/noparse] Variables ]

' Declare variables for storing measured RC times of the
' left & right photoresistors.
timeLeft VAR Word
timeRight VAR Word
'
[noparse][[/noparse] Main Routine ]

DO
GOSUB Test_Photoresistors
GOSUB Navigate
GOSUB Test_Switches
LOOP

[noparse][[/noparse] Subroutine - Test_Photoresistors ]

Test_Photoresistors:
HIGH 3·················································' Left RC time measurement.
PAUSE 3
RCTIME 3,1,timeLeft·
HIGH 4················································ ' Right RC time measurement.
PAUSE 3
RCTIME 4,1,timeRight
RETURN
'
[noparse][[/noparse] Subroutine - Navigate ]

Navigate:
IF (timeLeft < LeftThreshold) AND (timeRight < RightThreshold) THEN
PULSOUT 15, 850····························· ·' Both detect flashlight beam,
PULSOUT 14, 650····························· ·' full speed forward.
ELSEIF (timeLeft < LeftThreshold) THEN···· ' Left detects flashlight beam,
PULSOUT 15, 700······························ ·' move left.
PULSOUT 14, 700
ELSEIF (timeRight < RightThreshold) THEN·· ' Right detects flashlight beam,
PULSOUT 15, 800······························· ·' move right.
PULSOUT 14, 800
ELSE
PULSOUT 15, 750······························ ·‘ * THIS IS WHERE THE PROBLEM IS, WHEN NO··············
·PULSOUT 14, 750···························· ··· LIGHT IS SEEN····················· ·····
ENDIF
PAUSE 20···············································' Pause
RETURN

[noparse][[/noparse] Subroutine - Switches ]

GOSUB Test_Switches:
IF (IN5 = 0) THEN······························· ·' Left switch contacts
GOSUB Back_Up ·································· ' Back up & turn left
GOSUB Turn_Left
ELSEIF (IN7 = 0) THEN···················· ·· ' Right switch contacts
GOSUB Back_Up··································· ' Back up & turn right
GOSUB Turn_Right
ELSE
ENDIF
RETURN

[noparse][[/noparse] Subroutine - Other ]

·
Turn_Left:·············································· ' Left turn, about 90-degrees.
FOR pulseCount = 0 TO 20
PULSOUT 15, 650
PULSOUT 14, 650
PAUSE 20
NEXT
RETURN
Turn_Right:
FOR pulseCount = 0 TO 20···················· ' Right turn, about 90-degrees.
PULSOUT 15, 850
PULSOUT 14, 850
PAUSE 20
NEXT
RETURN
Back_Up:·································· ········· ··' Back up.
FOR pulseCount = 0 TO 40
PULSOUT 15, 650
PULSOUT 14, 850
PAUSE 20
NEXT
RETURN
·
·

Comments

  • ZootZoot Posts: 2,227
    edited 2007-03-14 17:04
    I have two suggestions -- one would be to use FSMs (Finite State Machines) for each aspect of your behaviors (e.g. obstacle avoidance, light following, etc). An example is attached below (this is not my code; I found it on the forums; it's a good simple example of FSMs in a subsumption engine). The use of such "machines" allows your bot to act like it's doing more than one thing at a time -- like following light, but avoiding an obstacle when neccessary. You've already got a nice little subsumption flow going, but you might benefit from each module being a little more "intelligent".

    Then, I would make some changes to the FSM used for following light so that the defined states "remember" the last direction and mode that the light sensors were in. This gives you a way to, say, move in a larger-radius circle towards the last "known" or "remembered" direction that you had some decent light. A conceptual flow chart might go something like this:

    - light L bigger? go left -> set "memory" bit left
    - light R bigger? go left -> set "memory" bit right
    - average light below some pre-defined threshold?
    no -> go to top
    yes -> circle wide (maybe 20" radius) in last "memory" direction -> set timeout
    timeout? bail on light following until your threshold is high again


    The demo Sumobot code by Parallax also has a simple version of the above scenario (if one IR detector acquires the target, the bot stores the "last" direction it saw the target at, so that if both detectors "lose" the target, the 'bot makes a best guess to circle widely in that last "known" direction").

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ltmhallltmhall Posts: 102
    edited 2007-03-15 13:15
    Would it really have to be as complicated as the boebot.bs2 code ? Where can I find more information
    on FSM's ?
  • ZootZoot Posts: 2,227
    edited 2007-03-15 14:17
    OK, try downloading this document -- it has some very clear discussion about Finite State Machines, how to diagram them, what they do, etc.

    www.parallax.com/dl/docs/prod/sic/AppliedSumo-v1.0.pdf

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ltmhallltmhall Posts: 102
    edited 2007-03-15 17:49
    In your previous post you described an example where FSM's were used when a IR detector sesnses and object and stores its last dircestion where it saw it. In this Sumobot document which example activity would this be ?
  • metron9metron9 Posts: 1,100
    edited 2007-03-15 18:19
    "However, when the robot was further away it wouldn’t sense the light
    and all it would do is turn in circles."

    Replace the photo sensors with light to frequency chips (sold here at parallax) Your robot will be able to find a light cigar in a dark room, not kidding those chips are amazing. I found a o2 monitor artical and built one using a red led and a uv led and the chip, it could sense the difference in light transmission difference in saturated oxygin in my finger tip. You will need a different input subroutine to read them but it is simple.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!
  • ZootZoot Posts: 2,227
    edited 2007-03-15 18:27
    Page 170 of the SumoBot PDF has a nice discussion of Finite State Machines. Even if you use better sensors, the concepts relating to FSMs will be invaluable.

    Some of the code in that section (as well as in the rest of the doc.) has "search patterns" for when the target is lost.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ltmhallltmhall Posts: 102
    edited 2007-03-16 15:12
    I read the SumoBot PDF and I understand a little more about FMS's. Howerver, I didn't find any information
    in the search patterns about storing the state where it last detected a target ? They show how to
    move and look around for a target, which I think is helpful, but didn't see anything about using
    the stored state.

    Post Edited (ltmhall) : 3/16/2007 3:37:38 PM GMT
  • ZootZoot Posts: 2,227
    edited 2007-03-16 15:32
    Sorry, I may have had my SumoBot manuals a bit mixed up. Check out page 41 of the SumoBot Manual:

    www.parallax.com/dl/docs/prod/robo/sumobotman.pdf

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ltmhallltmhall Posts: 102
    edited 2007-03-18 03:06
    Now that I've re-thought the process of the light following program for my robot, I guess I need suggestions
    on how to write the seach pattern when the robot dosen't see the light with both photoresistors ?

    Any suggestions would be appreciated ?
  • ZootZoot Posts: 2,227
    edited 2007-03-18 05:41
    This is "pseudo-code":

    
    motor VAR  Byte/Word (2)    'two element array for motor speeds
    
    if lightL + lightR / 2 > someThreshold then 'if you are brighter than ambient
        
       if lightL > lightR then                            'higher than ambient, save brighter direction bit
          lightBit = 0   '0 = left; 1 = right
       else
          lightBit = 1
       endif
       'more efficient way to do above:
       'lightBit = lightL - lightR >> 15
    
        motor(lightBit) = reverse      'turn towards brighter light as defined by "saved" light bit
        motor(1-lightBit) = forward
        duration = 20                      'keep duration "charged up" for timeout in search pattern
    else                                        'less than ambient, use saved bit from last good above ambient reading
        if duration > 0 then
            motor(lightBit) = reverse/2    'to turn in wide circle
            motor(1-lightBit) = forward
            duration = duration - 1         'timeout timer
        else
            motor(0) = forward           'you timed out, no light, go forward
            motor(1) = forward
         endif
    endif
    
    
    



    Now, since FSMs are so cool, the real way to do the above is to set it up as it's own FSM (where each state is, say, below ambient, above ambient). This way the FSM can keep track of what you *want* to do with light, but could still be subsumed (overridden) by your obstacle avoidance, remote control, whatever. And, an FSM with a duration countdown can let you "timeout" the search pattern if it doesn't reacquire above ambient light after X counts. There are more efficient (and many alternative ways) to do the above, but hopefully this gives you a clear enough outline to implement your own ideas.

    Is this helpful?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    Post Edited (Zoot) : 3/18/2007 5:47:05 AM GMT
  • ltmhallltmhall Posts: 102
    edited 2007-03-18 11:51
    Sorry I'm still kind of in the dark (I've on finished the " What a Microcontroller and Robotics with the Boe Bot manuals and some programing terms and techniques are new to me)·. First I would obtain the bright light anf ambient light values and create a threshold. Would I want to combine my Left threshold and Right threshold to create one threshold.

    If the average light of both photoresistors was greater than the threshold would I want the robot to go
    forward.Then the code works by checking to see if lightL is greater than the lightR.·If so lightbit is·equal to 0, and if not lightbit equals 1.


    I understand from your comment that the code below turns the robot·toward brighter light, but I don't reconize the code. Is this used to rotate the motors ? How would " forward and reversed" be defined at the
    begining of the program?

    motor(lightBit) = reverse 'turn towards brighter light as defined by "saved" light bit
    motor(1-lightBit) = forward
    duration = 20


    Also I don't understand the motor VAR Byte/Word (2) at the beginning of the code.
    I tried running using this code and I get a error from the line " motor VAR· Byte/Word (2)", am I missing something else ?

    Also would this bit of code be used as a subroutine like test_photoresistors or something ?


    Any further explanations would be really appreciated !

    Post Edited (ltmhall) : 3/18/2007 2:48:39 PM GMT
  • ZootZoot Posts: 2,227
    edited 2007-03-18 22:23
    Somebody said...
    Sorry I'm still kind of in the dark (I've on finished the " What a Microcontroller and Robotics with the Boe Bot manuals and some programing terms and techniques are new to me) . First I would obtain the bright light anf ambient light values and create a threshold. Would I want to combine my Left threshold and Right threshold to create one threshold.

    If the average light of both photoresistors was greater than the threshold would I want the robot to go

    That's just an idea for deciding if you have enough light to begin with.
    said...


    motor(lightBit) = reverse 'turn towards brighter light as defined by "saved" light bit
    motor(1-lightBit) = forward
    duration = 20


    That's pseudo code really. You could just as easily write:

    IF lightBit = 0 THEN
        turnLeft code
    ELSE
        turnRight code
    ENDIF
    
    



    It's more a structure, not real code to run. However you run your code, you've got lightBit to decide which way to turn, UNLESS the ambient light is marginal, in which case you start circling in the lightBit direction.

    Use some other variable to "countdown" once you've started circling, so you can give up at some point and have the 'bot do something else.
    said...
    Also I don't understand the motor VAR Byte/Word (2) at the beginning of the code.
    I tried running using this code and I get a error from the line " motor VAR Byte/Word (2)", am I missing something else ?

    It's not real code and won't compile. I often use arrays for my motors or paired sensors because it make some things easier.

    Whether or not it's a subroutine depends on how you want to use it, but here's another attempt at a pseudo-code "flowchart" for organizing what you have going on (I think):

    
    1. get light values: subroutine that reads light sensors
    2. calculate average/threshold: lightAvg = lightL + LightR / 2, or check out the difference threshold in Robotics with the Boe-bot
    3. decide if you have enough light to do anything interesting:
          if lightAVg < someNumberYouDecideWorks then set countdown timer to 20 and skip to step 7: you don't have  a very bright light
    4. lightBit = 0 if lightL < lightR, otherwise lightBit = 1: set lightbit
    5. turn left if lightBit =0, otherwise turn right
    6. go to step 1 and do it again
    7. you only got here because light was dim
    8. is countdown timer = 0? then go to step 11
    9. otherwise, if lightBit = 0 then circle wide left, otherwise circle wide right
    10. go to step 1 and do it again
    11. SOMETHING ELSE TO DO SINCE LIGHT ACQUISITION TIMED OUT
    12. go to step 1 and do it again
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ltmhallltmhall Posts: 102
    edited 2007-03-19 13:44
    I think I understand the flow chart a little bit better. I just have two question about the flow chart in your last post.
    In step 3 where the light AVg is compared to some threshold, you say “ set countdown timer to 20 and skip to step 7”,
    however, in your pseudo-code above it jump straight step 7. Would I want to remove duration =20 and

    put under the "else" command underneath it ?


    Also at step six you say “go to step 1 and do it again why would go to step 1, is it because you want to

    align both photoresistors in front of the light.


    First the photoresistor vales are measure and then a average (lightAVg) is created. Next lightAVg is compared to some threshold and if it’s less than this threshold
    the program jumps to where the duration is set to twenty and the duration is compared to zero. If lightAVg is greater than the threshold, lightL is compared to lightR. If lightL is greater than lightR than lightBit equals zero. If lightR is greater than lightL lightBit is equal to one. Next the robot moves right or left, depending on what the value of lightBit is equal to. The program loops itself until the average is less than the threshold. Next
    the duration is compared to zero. If the duration is greater than zero the robot turns in circles and the value of the duration is decremented by one. When the duration is greater than zero the timer times out and the robot moves forward.
  • ZootZoot Posts: 2,227
    edited 2007-03-19 14:09
    Think of step1 as the top of your main loop. Other things may be happening also, but that is where it all begins.

    Where you "charge up" the duration to an appropriate countdown value is really up to you and partially depends on how you set up your code. The important think is to set it BEFORE it gets used, and only once, so that your circling doesn't time out immediately.

    Otherwise it sounds like you've got a pretty good understanding of the flow of things. Remember there are always many ways to accomplish the same task. I would also emphasize that HOW you choose to decide that your light values aren't worth directly tracking may take some experimenting. Using an average ambient light value is one trick. You could also take the difference between the values and use that. You could also just check to see if one or the other sensor is very high/low.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ltmhallltmhall Posts: 102
    edited 2007-03-19 14:19
    So I could possibly put my ambient light value where you say "decide if you have enough light to do anything interesting" ?

    Also make sure that I set my duration = 20 before I check if it's greater than zero
  • ZootZoot Posts: 2,227
    edited 2007-03-19 15:43
    A) Yes.

    B) Yes. Remember that the "20" is just a number I made up. What the number is and how fast it counts down really depends on the rest of your program and code. For example, if your code loops through every 20ms or so (so you can refresh pulses) then a countdown of 20 would be a approx. 400ms (less than 1/2 second). It will take some experimenting.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
Sign In or Register to comment.