Shop OBEX P1 Docs P2 Docs Learn Events
Third Servo Motor — Parallax Forums

Third Servo Motor

JPGJPG Posts: 7
edited 2011-07-29 12:19 in Robotics
I'm putting together a sumobot for a competition, and my strategy is based on using a third servo motor as a winch to draw up a forklift-type tool in the front of the robot. I've connected the motor, and have used it to successfully operate the tool, but when I try to add winching capabilities to something simple like the basic competition code that comes with the sumo kit, the robot acts weird -- it's moved more slowly than usual, driven off the edge of the mat where before it wouldn't have, and done other strange stuff.

In addition to that, I'm having some difficulty with writing my own code that doesn't even involve the winch motor at all. My code is pretty ugly, mostly Frankensteined together out of sample code (This competition allows only a very very short prep time, and I'm not at all familiar with BASIC), but I'll reply to this in a little while with some code and problems that I've observed trying to run it.

I'm looking for any help I can get: general tips about things to watch out for while trying to use a third servo, specific problems with my setup, anything.

Comments

  • ercoerco Posts: 20,256
    edited 2011-07-27 16:19
    You have to run all 3 servos off a tight 20 ms loop. Sounds like you may have added a seperate routine (pulsout + pause 20) somewhere which is causing a problematic delay and interfering with your drive servos.

    If you're not a code wizard, consider using a DC motor instead of a servo. You can turn that on and off with a simple high or low command that closes a reed relay. It needn't interfere with your drive servo loop.

    Attach your code and maybe someone can help.
  • JPGJPG Posts: 7
    edited 2011-07-27 16:34
    Here it is... my code with all winch functionality removed. As promised, it's a mess -- I don't know data types in BASIC, when to use GOSUB vs GOTO, basically nothing. I'm fairly certain that the problem is in the "main code" section, probably under the "strategy" heading. What seems to happen is the robot makes it to the ELSE clause at the end (where it just spins around waiting to see an enemy) just fine, but doesn't do any of the other things when it finally gets IR input. The IR sensors themselves are working.
    ' -----[ Title ]----------------------------------------------------------------
    ' WALL-E
    ' {$STAMP BS2}                               ' Target = BASIC Stamp 2
    ' {$PBASIC 2.5}                              ' Language = PBASIC 2.5
    
    ' -----[ I/O Definitions ]------------------------------------------------------
    
    LMotor          PIN     13                      ' left servo motor
    RMotor          PIN     12                      ' right servo motor
    WMotor          PIN     5                       ' winch motor
    
    LLineSnsPwr     PIN     10                      ' left line sensor power
    LLineSnsIn      PIN      9                      ' left line sensor input
    RLineSnsPwr     PIN      7                      ' right line sensor power
    RLineSnsIn      PIN      8                      ' right line sensor input
    
    LFIrOut         PIN      4                      ' left IR LED output
    LFIrIn          PIN     11                    ' left IR sensor input
    RFIrOut         PIN     15                      ' right IR LED output
    RFIrIn          PIN     14                    ' right IR sensor input
    
    LSIrOut         PIN     2                      ' left IR LED output
    LSIrIn          PIN     1                    ' left IR sensor input
    RSIrOut         PIN     3                      ' right IR LED output
    RSIrIn          PIN     0                    ' right IR sensor input
    
    ' -----[ Constants ]------------------------------------------------------------
    
    LFwdFast        CON     1000                    ' left motor forward; fast
    LFwdSlow        CON      800                    ' left motor forward; slow
    LStop           CON      750                    ' left motor stop
    LRevSlow        CON      700                    ' left motor reverse; slow
    LRevFast        CON      500                    ' left motor reverse; fast
    
    RFwdFast        CON      500                    ' right motor forward; fast
    RFwdSlow        CON      700                    ' right motor forward; slow
    RStop           CON      750                    ' right motor stop
    RRevSlow        CON      800                    ' right motor reverse; slow
    RRevFast        CON     1000                    ' right motor reverse; fast
    
    WinchUp         CON     1000                    ' winch motor reeling in line
    WinchDown       CON      500                    ' winch motor letting out line
    WinchStop       CON      750                    ' winch motor stop
    
    IRNearFreq      CON    42000                    ' nearsighted IR
    IRRegFreq       CON    38500                    ' regular IR
    
    ' -----[ Variables ]------------------------------------------------------------
    
    leftSense       VAR     Word                    ' left sensor raw reading
    rightSense      VAR     Word                    ' right sensor raw reading
    blackThresh     VAR     Word                    ' QTI black threshold setting
    lineBits        VAR     Nib                     ' decoded sensors value
    lineLeft        VAR     lineBits.BIT1
    lineRight       VAR     lineBits.BIT0
    
    irBits          VAR     Byte                     ' storage for IR target data
    irRS            VAR     irBits.BIT3             ' State of Right Side IR
    irLS            VAR     irBits.BIT2             ' State of Left Side IR
    irRF            VAR     irBits.BIT1             ' State of Right Front IR
    irLF            VAR     irBits.BIT0             ' State of Left Front IR
    
    pulses          VAR     Byte                    ' counter for motor control
    counter         VAR     Byte
    temp            VAR     Byte
    
    '-------[EEPROM]--------
    RunStatus       DATA    $00                     ' run status
    
    ' -----[ Initialization ]-------------------------------------------------------
    
    Run_Check:                                      ' user Reset button as On-Off
      READ RunStatus, temp                          ' read current status
      temp = ~temp                                  ' invert status
      WRITE RunStatus, temp                         ' save status for next reset
      IF (temp = 0) THEN Set_Threshold              ' run now?
      END                                           '   -- no ... next time
    
    ' Sets black threshold to 1/4 the average of the two sensor readings.
    ' SumoBot must be placed over black playing surface before this code runs.
    
    Set_Threshold:                                  ' set QTI black threshold
      GOSUB Read_Line_Sensors
      blackThresh = (leftSense / 8) + (rightSense / 8)
    
    Start_Delay:                                    ' mandatory five second delay
      FOR temp = 1 TO 5
        PAUSE 900
        'INPUT StartLED                              ' blink each second
        'FREQOUT Speaker, 100, 2500, 3000            ' beep each second
      NEXT
    
    ' -----[ Main Code ]------------------------------------------------------------
    
    Main:
    
    DO
    
      GOSUB Read_Line_Sensors
    
       IF lineLeft = 1 AND lineRight = 1 THEN
          GOTO About_Face
       ELSEIF lineLeft = 1 THEN
          GOTO Spin_Left
       ELSEIF lineRight = 1 THEN
          GOTO Spin_Right
       ENDIF
    '================[ STRATEGY ]==================
    
    Label_1:
    
      GOSUB Read_IR_Sensors
    
      IF (irLF = 1 AND irRF = 1) THEN
        GOTO Lunge
    
      ELSEIF irLF = 1 THEN
        counter = 0
        DO UNTIL (irLF = 1 AND irRF = 1) OR counter > 30
          GOSUB Spin_Left2
          GOSUB Read_IR_Sensors
          counter = counter + 1
        LOOP
    
      ELSEIF irRF = 1 THEN
        counter = 0
        DO UNTIL (irLF = 1 AND irRF = 1) OR counter > 30
          GOSUB Spin_Right2
          GOSUB Read_IR_Sensors
          counter = counter + 1
        LOOP
    
      ELSEIF irLS = 1 THEN
        counter = 0
        DO UNTIL (irLF = 1 AND irRF = 1) OR counter > 30
          GOSUB Spin_Left2
          GOSUB Read_IR_Sensors
          counter = counter + 1
        LOOP
    
      ELSEIF irRS = 1 THEN                       ' Object right side?
        counter = 0
        DO UNTIL (irLF = 1 AND irRF = 1) OR counter > 30
          GOSUB Spin_Right2
          GOSUB Read_IR_Sensors
          counter = counter + 1
        LOOP
    
      ELSE
        DO UNTIL (irLF = 1 OR irRF = 1 OR irLS = 1 OR irRS = 1)
          GOSUB Spin_Right2
          GOSUB Read_IR_Sensors
        LOOP
      ENDIF
    
    LOOP
    '==============================================
    
    ' --[ Movement and Sensors]--
    
    Spin_Left:                                      ' right sensor was active
      FOR pulses = 1 TO 20
        PULSOUT LMotor, LRevFast
        PULSOUT RMotor, RFwdFast
        PAUSE 20
      NEXT
      GOTO Main
    
    Spin_Right:                                     ' left sensor was active
      FOR pulses = 1 TO 20
        PULSOUT LMotor, LFwdFast
        PULSOUT RMotor, RRevFast
        PAUSE 20
      NEXT
      GOTO Main
    
    Spin_Right2:                                     ' this one returns instead of going to main
      FOR pulses = 1 TO 5
        PULSOUT LMotor, LFwdFast
        PULSOUT RMotor, RRevFast
        PAUSE 20
      NEXT
      RETURN
    
    Spin_Left2:                                      ' this one returns instead of going to main
      FOR pulses = 1 TO 5
        PULSOUT LMotor, LRevFast
        PULSOUT RMotor, RFwdFast
        PAUSE 20
      NEXT
      RETURN
    
    About_Face:                                     ' both sensors on Shikiri line
      FOR pulses = 1 TO 10                          ' back up from edge
        PULSOUT LMotor, LRevFast
        PULSOUT RMotor, RRevFast
        PAUSE 20
      NEXT
      FOR pulses = 1 TO 30                          ' turn around
        PULSOUT LMotor, LFwdFast
        PULSOUT RMotor, RRevFast
        PAUSE 20
      NEXT
      GOTO Main
    
    Move_Fwd:
      GOSUB Creep_Forward
      GOTO Main
    
    Creep_Forward:
      FOR pulses = 1 TO 10
        PULSOUT LMotor, LFwdSlow
        PULSOUT RMotor, RFwdSlow
        PAUSE 20
      NEXT
      RETURN
    
    Lunge:                                          ' locked on -- go get him!
      FOR pulses = 1 TO 15
        PULSOUT LMotor, LFwdFast
        PULSOUT RMotor, RFwdFast
        GOSUB Read_Line_Sensors
        IF (lineBits = %11) THEN Match_Over         ' in sight and we're on the line
      NEXT
      GOTO Main
    
    ' If SumoBot can see the opponent with both "eyes" and both QTIs are
    ' detecting the border, we must have pushed the opponent out.
    
    Match_Over:
      FOR pulses = 1 TO 10                          ' stop motors
        PULSOUT LMotor, LStop
        PULSOUT RMotor, RStop
        PULSOUT WMotor, WinchStop
        PAUSE 20
      NEXT
      INPUT LMotor
      INPUT RMotor
    
      DIRS = $0000                                  ' disable all outputs
      GOTO Run_Check                                ' reset for next round
    
    Read_Line_Sensors:
      HIGH LLineSnsPwr                              ' activate sensors
      HIGH RLineSnsPwr
      HIGH LLineSnsIn                               ' discharge QTI caps
      HIGH RLineSnsIn
      PAUSE 1
      RCTIME LLineSnsIn, 1, leftSense               ' read left sensor
      RCTIME RLineSnsIn, 1, rightSense              ' read right sensor
      LOW LLineSnsPwr                               ' deactivate sensors
      LOW RLineSnsPwr
    
      ' convert readings to bits
      lineBits = %00
      LOOKDOWN leftSense, >=[blackThresh, 0], lineLeft
      LOOKDOWN rightSense, >=[blackThresh, 0], lineRight
      RETURN
    
    Read_IR_Sensors:
      FREQOUT LFIrOut, 1, IRNearFreq                ' modulate left front IR LED
      irLF = ~LFIrIn                                ' read input (1 = target)
      FREQOUT RFIrOut, 1, IRNearFreq                ' modulate right front IR LED
      irRF = ~RFIrIn                                ' read input (1 = target)
      FREQOUT LSIrOut, 1, IRRegFreq                 ' modulate left side IR LED
      irLS = ~LSIrIn                                ' read input (1 = target)
      FREQOUT RSIrOut, 1, IRRegFreq                 ' modulate right side IR LED
      irRS = ~RSIrIn                                ' read input (1 = target)
      RETURN
    




    Regarding my initial question about the winch, here's a pseudocode example of something that I tried to add to the "Lunge" section of "Mini Sumo 5.1 : Basic Competition Program"
    Lunge:                                          ' locked on -- go get him!
      FOR pulses = 1 TO 15
        PULSOUT LMotor, LFwdFast
        PULSOUT RMotor, RFwdFast
        GOSUB Read_Line_Sensors
        IF (lineBits = %11) THEN Match_Over         ' in sight and we're on the line
      NEXT
      ' for- next loop using pulsout command to raise tool using winch motor
      ' for- next loop using pulsout command to lower tool using winch motor
      GOTO Main
    

    this appeared to cause the robot to move significantly slower than it had been, and it also tended to drive off the edge of the mat, even though the border avoidance should have stopped it.
  • JPGJPG Posts: 7
    edited 2011-07-27 17:46
    After further consideration, and erco's comment, I think a better question might be how to make sure my winch motor and sensor reading doesn't extend the low time in between drive servo pulses. however, I still don't have a very good grasp about how to structure the order of my functions so that my low time doesn't suffer.

    -Does PAUSE mean that the robot doesn't do anything at all for x number of milleseconds?
    -Does the modulus function work in BASIC? If it does, would using it to split my QTI sensor readings (read left sensor on odd counts, right on evens) help me have a more efficient loop?
  • ercoerco Posts: 20,256
    edited 2011-07-28 00:11
    JPG wrote: »
    -Does PAUSE mean that the robot doesn't do anything at all for x number of milleseconds?

    Correct, it's dead time; nothing happens during a pause. Better to be doing something useful, like checking sensors umpteen or hundreds of times to while away the lonely (20) milliseconds...

    Look at driving all 3 servos simultaneously like this:

    z=750
    main:pulsout leftmotor,x
    pulsout rightmotor,y
    pulsout winch,z
    blah testsensor
    blah testsensor
    if blah calculate new x
    if blah calculate new y
    if blah calculate new z
    pause 5
    goto main

    Here you're driving your winch servo at zero speed (pulsout 750) in that fast loop until you decide to change z, which starts to rotate your servo. Notice that I used a pause 5 instead of 20. All your sensor tests, calculations and if checks takes some time, so if you have a lot of those, they will burn up some time and effectively reduce your pause time. In practice, many servos don't need a full 20 ms pause between pulsouts; they can use a shorter interval, but not longer. Test yours and see what works best for your servos.
  • JPGJPG Posts: 7
    edited 2011-07-29 12:19
    thanks for the help. I was eventually able to get something worked out, even though it wasn't optimal strategy. I lost the competition, but only by two points... and I learned a lot.
Sign In or Register to comment.