Shop OBEX P1 Docs P2 Docs Learn Events
Ping)))Dar "1 Scan Only, Please" — Parallax Forums

Ping)))Dar "1 Scan Only, Please"

RockoRocko Posts: 8
edited 2013-10-25 16:19 in Accessories
Hello,
I've gotten the Ping)))Dar program to run (on my Boe-Bot) as described but am still having a few issues.
How do I modify the code so the Ping)))Dar only scans once and then moves forward toward object.
My boebot goes through the scanning sequence, identifyies object, then moves forward maybe several inches. It then stops, goes through the scanning process again, moves forward another couple of inches, stops, scans again, etc.
Again, I want it to accept the initial scan and move forward to infinity.

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

Comments

  • Steph LindsaySteph Lindsay Posts: 767
    edited 2013-10-25 10:09
    That sounds like it is potentially resetting. Do you have a piezospeaker on P4 by any chance? A freqout 4, 3000, 3000 in the Initialization section would alert you to a reset.
  • ajwardajward Posts: 1,129
    edited 2013-10-25 15:57
    Hi Rocko...

    I would suggest making sure your batteries are fresh. The servos can draw a significant amount of current causing the BOE to reset, restarting the program. I had a similar problem with Ping roaming and it took me a bit to determine the batteries were weak.
    Try replacing the batteries and if the issue persists, we have another problem to sort out.

    Good Luck!

    Amanda
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-10-25 16:19
    Here's my guess.

    Change this section:
    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
    

    To this:
    DO    
        PULSOUT BotServoLeft, FwdLeftFast        ' Boe-Bot forward
        PULSOUT BotServoRight, FwdRightFast
        PAUSE 20
    
    
      LOOP
    

    I just removed all the distance checks and calculations once the robot starts moving toward the target. The robot will just keep going without looking where it's going anymore.
Sign In or Register to comment.