Shop OBEX P1 Docs P2 Docs Learn Events
Ping)))Dar Go To & Find Closest Object Issues — Parallax Forums

Ping)))Dar Go To & Find Closest Object Issues

RockoRocko Posts: 8
edited 2013-10-15 10:04 in BASIC Stamp
I have the Ping)))Dar Go To & Find Closest Object program up & running on my Boe-Bot but need some help with a couple of things.

The PingDar works as it should: scans, locates each side then middle of object, aligns wheels accordingly. Then it starts forward toward object but only gets several inches before it stops and repeats the scanning/locating sequence again. Then it starts forward again and only goes another couple of inches before it stops and starts the scan again. This process continues again and again.
I have to make note here that the object is only a 1-1/2" sq. wooden block, so when the PingDar gets to within ~6", it looses "site" of the object.
Does anyone know how I can modify the code so the PingDar only makes a couple of scans and after the second scan move forward indefinitely ?

I've tried modifying the code every which way but I'm at a loss on trying to get out of this loop.

Here's the code:
' -----[ Title ]--------------------------------------------------------------
' Smart Sensors and Applications - GoToClosestObject.bs2
' Sweep Ping))) Ultrasonic Rangefinder across 180-degrees and find the closest
' object.  Then calculate and execute the turn required to face the object.
' Travel forward until the object is less than or equal to 5 cm from the front
' of the rangefinder.

' IMPORTANT: This program has several constants that have to be tuned before
'            it will work right.  Follow the instructions in Smart Sensors
'            and Applications, Chapter 8, Activity #4 and #5 before you run
'            this program!

' {$STAMP BS2}                               ' Target device = BASIC Stamp 2
' {$PBASIC 2.5}                              ' Language = PBASIC 2.5

' -----[ I/O Definitions ]----------------------------------------------------

' Ping))) Ultrasonc Rangefinder and Mounting Bracket
PingServo      PIN     14                    ' Servo that directs Ping))) snsr
Ping           PIN     1                     ' Ping))) sensor signal pin

' Boe-Bot servo pins (Left and right are from driver's seat perspective.)
BotServoLeft   PIN     13                    ' Left drive servo
BotServoRight  PIN     12                    ' Right drive servo

StartLED     PIN        0                       ' display start delay

' -----[ Constants ]----------------------------------------------------------

' Ping))) mounting bracket constants
LimitLeft      CON     1189                  ' Bracket 90-degrees Left
LimitRight     CON     286                   ' Bracket 90-degrees Right
Limits         CON     LimitLeft + limitRight 'this added from Forum
Center         CON     750                   ' Center/0-degree pulse duration
Increment      CON     15                    ' Increment for pulse sweeping
MinSweep       CON     40                    ' Pulses -> 90-degree right

' Boe-Bot continuous rotation servo control constants
FwdLeftFast    CON     817                   ' Fast settings - straight ahead
FwdRightFast   CON     650
RotateRight    CON     763                   ' Boe-Bot rotate right pulse
RotateLeft     CON     740                   ' Boe-Bot rotate left pulse
BtwnPulses     CON     20                    ' ms between servo pulses

' Ping))) Ultrasonic Rangefinder constants
CmConstant     CON     2260                  ' Echo time -> cm with **
SinCosTo256    CON     517                   ' For */ -127..127 -> -256..256
Ms20           CON     330                   ' 20 ms worth of cm

' MSB sign (twos complement)
Negative       CON     1                     ' Negative sign (bit-15)
Positive       CON     0                     ' Positive sign (bit-15)

' Ping and turning axis geometry
PingDirToAngle CON     8454                  ' Servo pulse to angle ** con
PingAxleOffset CON     7                     ' 7 cm between ping))) and axis

' -----[ Variables ]----------------------------------------------------------

time           VAR     Word                  ' Ping))) echo time
pingDir        VAR     Word                  ' Pulse duration -> direction
pingRev        VAR     Word                  ' Pulse duration -> direction for reversed servo
                                             ' added from Forum
x              VAR     Word                  ' x coordinate
y              VAR     Word                  ' y coordinate
distance       VAR     Time                  ' Object centimeter distance
markDir        VAR     y                     ' Pulse points to closest object
rightMark      VAR     x                     ' Pulse to object's right side
leftMark       VAR     pingDir               ' Pulse to object's left side
pulses         VAR     x                     ' +/- brads to turn toward object
PrevDist       VAR     Byte                  ' Previous distance measurement
angle          VAR     Byte                  ' Servo angle from right in brads
counter        VAR     angle                 ' Loop counter
minDist        VAR     angle                 ' Minimum distance measurement
sweepInc       VAR     Nib                   ' Increment for servo sweep
sweepDir       VAR     Bit                   ' Increment/decrement pingDir
xSign          VAR     Bit                   ' Stores sign of x variable
ySign          VAR     xSign                 ' Stores sign of x variable
pSign          VAR     Bit                   ' Sign of pulses variable
edgesFound     VAR     Bit                   ' Navigation flag
temp         VAR        Byte

' -----[ Initialization ]-----------------------------------------------------

' -----[ EEPROM Data ]-----------------------------------------------------

RunStatus    DATA       $00                     ' run status

' -----[ Initialization ]--------------------------------------------------

Reset:
  READ RunStatus, temp                          ' read current status
  temp = ~temp                                  ' invert status
  WRITE RunStatus, temp                         ' save for next reset
  IF (temp > 0) THEN END                        ' run now?

Start_Delay:
  HIGH StartLED                                 ' show active
  PAUSE 5000                                    ' start delay
  LOW StartLED                                  ' LED off

                                             ' following from Forum
pingDir = LimitRight                         ' Start servo at 0-degrees

FOR counter = 1 TO 40                        ' Initialize servo position
  'PULSOUT PingServo, pingDir               ' Forum: removed & replaced by next 2 lines
  pingRev = Limits - pingDir
  PULSOUT PingServo, pingRev
  PAUSE 20
NEXT

sweepInc = Increment                         ' Set the sweep increment

' -----[ Main Routine ]-------------------------------------------------------

GOSUB Get_Ping_Cm                            ' First distance measurement

DO UNTIL distance <= 5                       ' Repeat until distance <= 5 cm

  edgesFound = 0                             ' Clear edges found flag

  DO UNTIL edgesFound = 1                    ' Repeat until edges found = 1
    GOSUB Face_Closest_Object                ' Find & face closest object
  LOOP

  GOSUB Get_Ping_Cm                          ' Get current distance

  DO UNTIL distance <= 5                     ' Drive toward object
    prevDist = distance MAX 255              ' Current distance -> previous
    GOSUB Get_Ping_Cm                        ' Get new distance
    PULSOUT BotServoLeft, FwdLeftFast        ' Boe-Bot forward
    PULSOUT BotServoRight, FwdRightFast
    PAUSE BtwnPulses - (distance / Ms20)     ' 20 ms pause between pulses
    IF distance >= prevDist + 5 THEN EXIT    ' Exit if distance increasing
  LOOP

LOOP                                         ' Main routine's outermost loop

END

' -----[ Subroutines - BoeBot_Turn_Brads ]-----------------------------------

' Boe-Bot turns a certain number of binary radians to face an object.

BoeBot_Turn_Brads:

  IF pSign = Positive THEN
    FOR counter = 0 TO ABS(pulses)
      PULSOUT BotServoLeft, RotateRight
      PULSOUT BotServoRight, RotateRight
      PAUSE BtwnPulses - (distance / Ms20)
    NEXT
  ELSE
    FOR counter = 0 TO ABS(pulses)
      PULSOUT BotServoLeft, RotateLeft
      PULSOUT BotServoRight, RotateLeft
      PAUSE BtwnPulses - (distance / Ms20)
    NEXT
  ENDIF

  RETURN

' -----[ Subroutines - Face_Closest_Object ]----------------------------------

' Scan for closest object using a Ping))) rangefinder mounted on a standard
' servo.  Locate the middle fo the object, and turn Boe-Bot to face it.

Face_Closest_Object:

  ' Initialize sweep increment.
  sweepInc = Increment

  ' Start Servo rotated to the far right.
  pingDir = LimitRight
  GOSUB Point_At_PingDir

  ' Make minDist large and sweepDir positive (0).  Single_Sweep sweeps
  ' left -> right while measuring object distances and stores the direction
  ' of the closest object in markDir.
  minDist = 65535
  sweepDir = Positive
  GOSUB Single_Sweep

  ' Point the servo in the direction of the closest distance measurement.
  pingDir = markDir
  GOSUB Point_At_PingDir

  ' Scan to find object's right side.
  GOSUB Find_Right_Side
  IF edgesFound = 0 THEN RETURN

  ' Point the servo in the direction of the closest distance measurement.
  pingDir = markDir
  GOSUB Point_At_PingDir

  ' Scan to find object's right side.
  GOSUB Find_Left_Side
  IF edgesFound = 0 THEN RETURN

  ' Average the angles to the object's left and right sides.  That's the
  ' middle of the object.  Point rangefinder in that direction.
  pingDir = leftMark + rightMark / 2
  GOSUB Point_At_PingDir

  ' At this point, the Ping))) should be pointing directly at the closest
  ' object.

  ' Calculate the angle to the object's angle in brads, and turn the
  ' Boe-Bot to face that angle.
  GOSUB Turn_Angle_Adjust
  GOSUB BoeBot_Turn_Brads

  ' Face Ping))) rangefinder straight ahead.
  pingDir = Center
  GOSUB Point_At_PingDir

  RETURN

' -----[ Subroutines - Find_Left_Side ]---------------------------------------

' Scan left until the measured distance is 10 cm beyond the closest distance,
' which is assumed to mean the object's side has been found.

' If the object's side has been found within the 180-degree field of vision,
' set edgesFound = 1 and store the pulse duration (pingDir) at which the
' object was found in the leftMark variable.

' If the side was not found by the 180-degree point in the scan, rotate the
' Boe-Bot until the edge is found, and then set edgesFound to 0 signifying
' that the scan will have to be repeated because the Boe-Bot rotated
' to find the side, which would otherwise cause the markDir variable to
' store an incorrect value.

Find_Left_Side:

  sweepDir = Positive
  distance = minDist
  sweepInc = 1

  DO UNTIL distance > minDist + 10
    GOSUB Sweep_Increment
    GOSUB Get_Ping_Cm
    IF pingDir >= LimitLeft - 10 THEN
      pingDir = LimitLeft - 50
      GOSUB Point_At_PingDir
      DO UNTIL distance > minDist + 10
        PULSOUT BotServoLeft, RotateLeft
        PULSOUT BotServoRight, RotateLeft
        GOSUB Get_Ping_Cm
        PAUSE 20
      LOOP
      edgesFound = 0
      RETURN
    ENDIF
  LOOP
  leftMark = pingDir
  edgesFound = 1
  RETURN

' -----[ Subroutines - Find_Right_Side ]--------------------------------------

' Mirror image of Find_Left_Side.

Find_Right_Side:

  sweepDir  = Negative
  distance = minDist
  sweepInc = 1

  DO UNTIL distance > minDist + 10
    GOSUB Sweep_Increment
    GOSUB Get_Ping_Cm
    IF pingDir <= LimitRight + 10 THEN
      pingDir = LimitRight + 50
      GOSUB Point_At_PingDir
      DO UNTIL distance > minDist + 10
        PULSOUT BotServoLeft, RotateRight
        PULSOUT BotServoRight, RotateRight
        GOSUB Get_Ping_Cm
        PAUSE 20
      LOOP
      edgesFound = 0
      RETURN
    ENDIF
  LOOP
  rightMark = pingDir
  edgesFound = 1
  RETURN

' -----[ Subroutine - Get_Ping_Cm ]-------------------------------------------

' Gets Ping))) rangefinder measurement and converts time to centimeters.
' Distance may be declared as time to save variable space.

Get_Ping_Cm:

  PULSOUT Ping, 5
  PULSIN Ping, 1, time
  distance = time ** CmConstant

  RETURN

' -----[ Subroutines - Point_At_PingDir ]-------------------------------------

' Points servo mounted Ping))) rangefinder at an angle determined by the
' value of the pingDir variable.

Point_At_PingDir:

  FOR counter = 0 TO MinSweep
    ' PULSOUT PingServo, pingDir               ' Forum: removed & replaced by next 2 lines
  pingRev = Limits - pingDir
  PULSOUT PingServo, pingRev
    PAUSE BtwnPulses
  NEXT

  RETURN

' -----[ Subroutine - Polar_To_Cartesian ]------------------------------------

' Calculates x and y (Cartesian coordinates) given distance and angle
' (polar coordinates).

Polar_To_Cartesian:

  ' Calculate left/right component.
  x = COS angle                              ' Polar to Cartesian
  xSign = x.BIT15                            ' Store sign bit
  x = ABS(x) */ SinCOsTo256                  ' Polar to Cartesian continued
  x = distance */ x
  IF xSign = negative THEN x = -x            ' Correct sign with sign bit

  ' Calculate straight ahead component.
  y = SIN angle                              ' Polar to Cartesian
  ySign = y.BIT15                            ' Store sign bit
  y = ABS(y) */ SinCOsTo256                  ' Polar to Cartesian continued
  y = distance */ y
  IF ySign = negative THEN y = -y            ' Correct sign with sign bit

  RETURN

' -----[ Subroutines - Single_Sweep ]-----------------------------------------

' Do one sweep, and find the closest distance measurement and the
' pulse value that points the servo in that direction.

Single_Sweep:

  DO UNTIL pingDir >= LimitLeft
    GOSUB Sweep_Increment
    GOSUB Get_Ping_Cm
    IF distance < minDist THEN
      minDist = distance
      markDir = pingDir
    ENDIF
  LOOP

  RETURN

' -----[ Subroutine - Sweep_Increment ]---------------------------------------

' Increment/decrement the position of the servo that directs the Ping)))
' rangefinder. When pingDir goes outside either LimitRight or LimitLeft,
' the sweep direction toggles.

Sweep_Increment:

  ' Change sweepDir for adding/subtracting increment if at rotation limit.
  IF pingDir <= LimitRight THEN
    sweepDir = Positive
  ELSEIF pingDir >= LimitLeft THEN
    sweepDir = Negative
  ENDIF

  ' Add/subtract increment to/from pingDir.
  IF sweepDir = negative THEN
    pingDir = pingDir - sweepInc
  ELSEIF sweepDir = Positive THEN
    pingDir = pingDir + sweepInc
  ENDIF

  ' Send positioning pulse to Ping))) Mounting Bracket servo.
  ' PULSOUT PingServo, pingDir               ' Forum: removed & replaced by next 2 lines
  pingRev = Limits - pingDir
  PULSOUT PingServo, pingRev

  RETURN

' -----[ Subroutines - Turn_Angle_Adjust ]------------------------------------

' Adjusts required turn angle based on 7 mm offset of Ping))) rangefinder from
' Boe-Bot's turning axis.

Turn_Angle_Adjust:

  ' Get the object's distance at its center.
  GOSUB Get_Ping_Cm

  ' Position servo & calculate angle from far-right in brads.
  angle = pingDir - 250 ** PingDirToAngle

  GOSUB Polar_To_Cartesian

  ' Add distance between Ping))) and center of Boe-Bot axis.
  y = y + PingAxleOffset

  ' Recalculate the turning angle with respect to Boe-Bot's turning axis.
  angle = x ATN y
  pulses = 64 - angle
  pSign = pulses.BIT15

  RETURN

Thanks for your help!

Comments

  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2013-10-15 10:04
    This sounds suspiciously like a low-battery issue. Have you tried a fresh set of batteries? Another way you can detect if the BASIC Stamp Module is browning out is to have it play a tone or light an LED briefly only at the beginning of the code. If this happens more than once you know your program is being restarted due to a brownout condition.
Sign In or Register to comment.