Shop OBEX P1 Docs P2 Docs Learn Events
Joystick/5-position switch to replicate PTZ Controller — Parallax Forums

Joystick/5-position switch to replicate PTZ Controller

FalconFalcon Posts: 191
edited 2012-05-28 08:31 in General Discussion
I’m planning to build a camera controller from either the Parallax joystick or 5-position switch. I don’t have the servos yet but am combing through code from forum posts to get an idea of how this will work compared to the security system I currently have. It will eventually be wireless via XBee, but I want to get a hard-wired mock-up working first.

My security system includes a Prosumer-grade PTZ (Pan/Tilt/Zoom) camera that is controlled by a Joystick-equipped controller via RS485. The joystick is spring-loaded to the center position. The camera’s Pan and Tilt movements occur while the joystick is not in the center position. The speed of the movement is based on the displacement from the center (neutral) position, i.e. it barely creeps if the joystick is only a few mm from the center but is quite fast when the joystick is at it’s limit. If the joystick is held at one position, the camera continues to move but at the (steady) speed determined by the displacement from center. When the joystick is released and returns to center, the camera remains at the same position until the joystick is again moved away from the center position. The distance from this center position only determines the speed at which the camera moves:

Since the Parallax joysticks and 5-position switches are spring-loaded to the center (neutral) position, the code examples I’ve seen seem like the servos will follow the knob and return to the “neutral” position when the joystick is released, and not remain at their last positions.

What would be the approach to mimic the PTZ controller described above? The key parameters are:

Servos move anytime joystick is not at center (mandatory)
Servo speed depends on displacement from center (nice to have)
Servo speed remains steady if joystick held stationary away from center
Servos remain stationary when joystick is released. (mandatory)

Thoughts?


falcon

Comments

  • john_sjohn_s Posts: 369
    edited 2012-05-17 13:09
    I'd start with Gordon's reply in http://forums.parallax.com/showthread.php?139064-Problem-with-the-Parallax-5-position-switch-27801

    5-position switch might be a bit harder to implement your second and 3-rd requirements as they seem to be mutually exclusive and require some more states than just the 2 provided by a simple ON-OFF switch.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-05-17 16:51
    I don't think I understand what you want to do.

    You have a PTZ camera with a joystick. Does the PT mount not come with servos already?

    Do you want to mimic the signal on the RS485 line with your own joystick?

    Whatever controller you are using to read the joystick and control the servos can certainly not return to center if that's what you want. It's just a small matter of programming.

    Do you have a microcontroller in mind? Reading joystick values (or 5-position switch values) and moving servos are pretty easy stuff for any microcontroller. Mimicking the RS485 joystick controller might be a problem for some microcontrollers.
  • kwinnkwinn Posts: 8,697
    edited 2012-05-17 17:05
    Do you want to use the 5 position switch or the parallax joystick, or both together for this?
  • FalconFalcon Posts: 191
    edited 2012-05-17 17:45
    Duane Degn,
    I mentioned the PTZ controller and camera just as an example of the camera movements I want to mimic with either a BSp or a Prop and two servos. The camera will be mounted to a wheeled robot. All of my experience so far is with the BS2 line, but I will begin the Prop EK soon so that is also an option.
    I'm trying to do this with two servos (and eventually XBees) to avoid using a commercial PTZ camera on the robot and having to generate and send the necessary RS-485 signals wirelessly.

    kwinn,
    The PTZ controller uses a joystick so that was my first thought. But the 5-position switch would be fine if it will work. I understand that the 5-position switch will not allow variable servo speed but that is not a strict requirement. The ability to move the servos and have them remain at a stationary position when the joystick or switch is released is the most important aspect.

    falcon
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-05-17 18:07
    This will be much easier to do with a Propeller. Mainly because of the serial communication through the XBee. A BS2 wouldn't be able to be listening to the XBee at the same time it was refreshing a servo, this isn't an issue with a Prop since it can use a cog to continuously listen to the serial port.

    The joystick/servo interaction you're looking for isn't an issue for either the Propeller or a BS2.

    One option with the 5-position switch is to have the camera move faster the longer the swich is held in one position.

    Depending on your enclosure requirements, there are lots of options to chose from as input devices. One inexpensive input device I really like is the Wii Nunchuck. It would only require two IO pins on a Prop (which could be shared with other I2C devices).

    I'd strongly suggest using a some sort of analog input like a joystick instead of a 5-position switch. An analog input (such as joystick or Nunchuck) would allow a lot more control than just on or off inputs.
  • kwinnkwinn Posts: 8,697
    edited 2012-05-17 18:40
    You might also want to consider using 2 pots to make your own joystick substitute. They could be coupled so that they mimic the actual motion of the camera. One pot would allow you to turn it clockwise/counter clockwise like the camera does, and it would be connected to the other pot to allow it to tilt forwards/backwards.
  • xanaduxanadu Posts: 3,347
    edited 2012-05-17 18:45
    I just did this with a Propeller, XBee, two servos and an IP Cam. It's a fun project.

    What camera did you have in mind?

    A joystick will be easy enough to use and give you better control, especially if your camera does any kind of zoom.
  • FalconFalcon Posts: 191
    edited 2012-05-18 04:43
    xanadu wrote: »
    I just did this with a Propeller, XBee, two servos and an IP Cam. It's a fun project.

    What camera did you have in mind?

    A joystick will be easy enough to use and give you better control, especially if your camera does any kind of zoom.

    xanadu,
    I have several composite-output bullet video cameras now but all are non-zoom. I'm searching for one that has a zoom function that can be manipulated with a 3rd servo. I have a 1500 mW 900 MHz TX/RX that I plan to use to get that video to my base unit..

    I would certainly consider an IP camera if I could get a reliable signal over a 200 yd range through a wooded area. That may require a repeater though.

    Do you have a thread on this project, or code and a schematic that you could share?

    I appreciate your help.

    falcon
  • FalconFalcon Posts: 191
    edited 2012-05-18 04:56
    Duane Degn wrote: »
    This will be much easier to do with a Propeller. Mainly because of the serial communication through the XBee. A BS2 wouldn't be able to be listening to the XBee at the same time it was refreshing a servo, this isn't an issue with a Prop since it can use a cog to continuously listen to the serial port.

    If I stay with the BS2 I was planning to use a ServoPal to offload any servo functions. However, it looks more and more like I should use the Propeller for this project.
    Duane Degn wrote: »
    I'd strongly suggest using a some sort of analog input like a joystick instead of a 5-position switch. An analog input (such as joystick or Nunchuck) would allow a lot more control than just on or off inputs.

    In that regard, the joystick does seem to be the better choice. I have the Parallax joystick to test with but have just discovered that many use a Playstation controller. With that I could integrate the robot drive control and the PTZ camera function into one controller with buttons left to activate lights and the TX only when required.

    I appreciate you taking the time to reply.

    falcon
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-05-18 05:40
    Falcon wrote: »
    In that regard, the joystick does seem to be the better choice. I have the Parallax joystick to test with but have just discovered that many use a Playstation controller. With that I could integrate the robot drive control and the PTZ camera function into one controller with buttons left to activate lights and the TX only when required.

    The PlayStation 2 controller is pretty cool. Did you know 12 of the buttons are pressure sensitive? You could use a button to control a servo and control its speed by how hard you're pressing the button. (I need to try this myself soon.)

    I haven't added control of the Dual Shock motors yet, but it's on my todo list. If you want to try use the Dual Shock feature before I add it, let me know, and I'll try to move it up on my priority list.

    I updated one of the objects for the PS2 to read the analog values of the buttons. My object also automatically updates the joystick and button data from a separate cog. If you try it and have any trouble let me know. I want to make the object easy to use so I'd appreciate the feedback from someone new to the Propeller.

    XBees are very nice wirless devices. I have a bunch myself. The problem is they are kind of expensive. I use a lot of Nordic nRF24L01+ modules in my projects. These things are very inexpensive (less than $2.50). You could get 10 of the Nordic modules for the price of one XBee. In some ways the Nordic modules are better than XBees. The Nordic modules have a faster communication rate than XBees partially do to using SPI to communicate rather than asychronous serial. The SPI communication protocol is also what makes the Nordic modules harder to use. I have an object for the Nordic modules and again, if you use it and have any trouble, let me know, and I'll try to help.

    As much as I like XBees, it pains me to see how much of the cost of a robot can be increased by price of a couple of XBees.

    The servo object that comes with the Propeller tool does a great job. I have a bunch of servo projects myself including my QuickStart servo tester. There's a very simple servo demo in post #15 of that thread. The servo demo in the Prop Tool's "_demo" folder is also fine.

    If you have questions about any of the objects I just linked to feel free to ask a question in the object's thread (or start a new thread if you want). I bet you wont be the only one to have those same questions.

    The Prop is harder to learn than the BS2, but it's really just about as perfect a microcontroller for robotic projects as you could ask for. It is well worth the effort to learn how to use. People in the Propeller Forum are very helpful. If you get stuck, just ask a question there.

    Wouldn't robotics be fun without having to worry if your program loop is short enough to refresh the servos every 20ms?
  • xanaduxanadu Posts: 3,347
    edited 2012-05-18 10:55
    Falcon wrote: »
    Do you have a thread on this project, or code and a schematic that you could share?

    Pan Tilt action- http://www.youtube.com/watch?v=j_TYHeeWPJ8

    Here's my current code - http://dl.dropbox.com/u/79058769/xbee_robot%20w%20ptz%20v9.spin (thanks to the help of this forum)

    In my code there is no provision for moving it with an analog joystick, but I'm also controlling it from my PC, not another microcontroller. So basically my project is only good for your camera side.

    One thing I noticed off the bat, standard servos only turn 180 degrees. Regular servos can be used with limit switches to give you more viewing options.



    1177115618
  • FalconFalcon Posts: 191
    edited 2012-05-20 16:39
    Since I have the 27800 Joystick, I decided to just see how well it controls two servos. I started with some code from GWJax. Scale and Offset values to be finalized.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    ' Running 2 servos with a joystick using RCTIME to record the pot's values.
    ' Make sure that the JoyStickRCTimeRecorder.bs2 has been run and you have recorded
    ' the Values for the Max and Min Pot on the Joystick.
    '
    ' Calculate the RCUDMin and RCUDMax scaling using your numbers that you got
    ' Use this formula to insert it into the Variables settings for TimeUDMin, TimeUDMax, TimeRlMin, TimeRLMax
    ' TimeMax: YourMaxReadng x (500 / YourMaxReading)= YourMaxReading x YourMinReading
    ' TimeMin: YourMinReading x (500 / YourMaxReading) scaling and Offset
    ' Do this for each Pot to start your Sc
    ' by GWJax
    
    '=================================================================================
    '-------------------------------- Set variables and Pins -------------------------
    '=================================================================================
    
    RTS       PIN                14        ' For Right Servo
    LTS       PIN                15        ' Set Left Servo
    RCUD      PIN                7         ' Set Up Down Pot to pin 7
    RCRL      PIN                8         ' Set Right Left Pot to pin 8
    ScaleUD   CON                1100       ' Scale by 0.724 (X 256 for */) 0.724 is from your calculations for Scale Right
                                           ' Change 185 to your correct calculation
    ScaleRL   CON                1100       ' Scale for left servo
    Offset    CON                200       ' Offset by 500
    TimeUD    VAR                Word      ' Records value for UD RC results
    TimeRL    VAR                Word      ' Records value for RL RC results
    CenterUD  VAR                Word      ' Records Center Value
    CenterRL  VAR                Word      ' Records Center Value
    
    '=================================================================================
    '------------------------------ Main Routine -------------------------------------
    '=================================================================================
    
    LOW RCUD  ' Discharge Cap
    LOW RCRL  ' Discharge Cap
    'IF TimeUD = 1 OR TimeUD = 0 THEN GOTO Bug ' Stop program POT failed
    'IF TimeRL = 1 OR TimeRL = 0 THEN GOTO Bug ' Stop program POT failed
    
    Main:
      DO
        GOSUB PotRCTime
          TimeUD = TimeUD */ ScaleUD
          TimeUD = TimeUD + Offset
          TimeRL = TimeRL */ ScaleRL
          TimeRL = TimeRL + Offset
      PULSOUT RTS, TimeUD ' Send pulses to servo.
      PULSOUT LTS, TimeRL
        PAUSE 18
      LOOP
    
    
    '=================================================================================
    '-------------------------- Get Joystick Center Values ---------------------------
    '=================================================================================
    
    JoyStickCenter:
    
    HIGH RCUD
        PAUSE 1 ' Charge Cap
        RCTIME RCUD, 1, CenterUD ' Get Recording for TimeUD
      LOW RCUD   ' Discharge UD Cap
      HIGH RCRL
        PAUSE 1 ' Charge Cap
        RCTIME RCRL, 1, CenterRL ' Get Recording for TimeRL
      LOW RCRL ' Discharge RL Cap
      RETURN
    
    '=================================================================================
    '------------------------------ Record Pot Values --------------------------------
    '=================================================================================
    PotRCTime:
    
      HIGH RCUD
        PAUSE 1 ' Charge Cap
        RCTIME RCUD, 1, TimeUD ' Get Recording for TimeUD
      LOW RCUD   ' Discharge UD Cap
      HIGH RCRL
        PAUSE 1 ' Charge Cap
        RCTIME RCRL, 1, TimeRL ' Get Recording for TimeRL
      LOW RCRL ' Discharge RL Cap
      RETURN
    
    '==================================================================================
    '------------------------------ Pot Failure ---------------------------------------
    '==================================================================================
    Bug:
    DEBUG "BUG", cr
    STO
    

    While going through the WAM text Ver 3.0, page 158 has me record the RC time variables for the pots. I get the following readings:


    Left Center Right
    L/R 0 30 247


    Down Center Down
    U/P 0 24 233

    After loading the code I see that 95% of the servo travel occur when moving the joystick from the center poisition to either the Right or Up positions. I suppose this is related to the Center time variables of 30 and 24 being now where near the center points. If these values were closer to the center of the range (247/2=124 and 233/2=117) I would see the servo movement more evenly divided.

    I under stand the the Endpoints can be scaled and offset to adjust for the actual servo travel. I don't see any mechanical ajustment on the Joystick. Is there any way to compensate for the lopsided center point time values?

    falcon
  • kwinnkwinn Posts: 8,697
    edited 2012-05-20 17:03
    This is probably due to the nonlinear charge/discharge characteristic of an r/c circuit. If you used a constant current to charge/discharge the capacitor the times would be much more linear.
  • FalconFalcon Posts: 191
    edited 2012-05-28 08:31
    I was able to source a used Playstation Controller and have it working with my BS2. I'll be moving to the Propeller later this summer but want to move along the "proof of concept" part of this project in the mean time.

    I started, as many do, with some good 'ole Jon Williams code and added the subroutine to move the two servos:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    '
    ' =========================================================================
    ' -----[ Program Description ]---------------------------------------------
    ' This program demonstrates the essential interface between the BASIC
    ' Stamp and a Sony PlayStation (or compatible) game controller. This
    ' code assumes that the clock signal is inverted between the Stamp and
    ' the controller to allow simpler [less sophisticated] interface with
    ' SHIFTOUT and SHIFTIN.
    '
    ' -----[ Revision History ]------------------------------------------------
    ' -----[ I/O Definitions ]-------------------------------------------------
    PsxAtt        PIN        7         ' PSX joystick interface Yellow Wire
    PsxClk        PIN        6         ' PSX joystick interface Blue Wire
    PsxCmd        PIN        5         ' PSX joystick interface Orange Wire
    PsxDat        PIN        4         ' PSX joystick interface Brown Wire
    UDServo       PIN        8         ' Right Servo
    RLServo       PIN        9         ' Left Servo
    ' -----[ Constants ]-------------------------------------------------------
    Inverted      CON        1         ' inverted clock signal
    ClockMode     CON        Inverted
    ' -----[ Variables ]-------------------------------------------------------
    idx           VAR        Byte      ' loop counter
    psxOut        VAR        Byte      ' byte to controller
    psxIn         VAR        Byte      ' byte from controller
    psxID         VAR        Byte      ' controller ID
    psxThumbL     VAR        Byte      ' left thumb buttons
    psxThumbR     VAR        Byte      ' right thumb buttons
    psxStatus     VAR        Byte      ' status ($5A)
    psxJoyRX      VAR        Byte      ' r joystick - X axis
    psxJoyRY      VAR        Byte      ' r joystick - Y axis
    psxJoyLX      VAR        Byte      ' l joystick - X axis
    psxJoyLY      VAR        Byte      ' l joystick - Y axis
    TimeUD        VAR        Word      ' Records value for UD RC results
    TimeRL        VAR        Word      ' Records value for RL RC results
    CenterUD      VAR        Word      ' Records Center Value
    CenterRL      VAR        Word      ' Records Center Value
    ScaleY        CON        883       ' Scale by 3.52
    ScaleX        CON        883       ' Scale for left servo
    Offset        CON        210       ' Offset
    
    ' -----[ EEPROM Data ]-----------------------------------------------------
    ' -----[ Initialization PSX Controller]------------------------------------
    Setup:
    HIGH PsxAtt                        ' deselect PSX controller
    OUTPUT PsxCmd
    PsxClk = ~ClockMode                ' release clock
    OUTPUT PsxClk                      ' make clock an output
    
    ' -----[ Program Code ]----------------------------------------------------
    Main:
    DO
    GOSUB Get_PSX_Packet_Fast          ' type and packet
    DEBUG HOME, "Type = "
    IF (psxStatus = $5A) THEN
    DEBUG IHEX2 psxId, " (", IHEX2 psxStatus, ")",
    CLREOL, CR, CR,
    BIN8 psxThumbL, " ", BIN8 psxThumbR, " "
    IF (psxId <> $41) THEN
    DEBUG DEC3 psxJoyLX, " ", DEC3 psxJoyLY, " ",
    DEC3 psxJoyRX, " ", DEC3 psxJoyRY, CR, CR
    ELSE
    DEBUG CLREOL
    ENDIF
    ELSE
    DEBUG "Unknown. No response.", CR, CLRDN
    'PAUSE 1000
    ENDIF
    GOSUB Move_Servos
    LOOP
    END
    
    ' Transmit psxOut to, and receive psxIn from the
    ' PSX controller
    PSX_TxRx:
    FOR idx = 0 TO 7
    PsxCmd = psxOut.LOWBIT(idx) ' setup command bit
    PsxClk = ClockMode ' clock the bit
    psxIn.LOWBIT(idx) = PsxDat ' get data bit
    PsxClk = ~ClockMode ' release clock
    NEXT
    RETURN
    
    ' This routine combines manual and built-in shifting
    ' routines to get the best speed and all valid data.
    '
    ' Execution time on BS2 is ~40 ms.
    Get_PSX_Packet_Fast:
    'IF (ClockMode = Direct) THEN Get_PSX_Packet ' redirect if not inverted
    LOW PsxAtt ' select controller
    SHIFTOUT PsxCmd, PsxClk, LSBFIRST, [$01] ' send "start"
    psxOut = $42 : GOSUB PSX_TxRx ' send "get data"
    psxId = psxIn ' save controller type
    SHIFTIN PsxDat, PsxClk, LSBPOST, [psxStatus] ' should be $5A ("ready")
    SHIFTIN PsxDat, PsxClk, LSBPOST, [psxThumbL]
    SHIFTIN PsxDat, PsxClk, LSBPOST, [psxThumbR]
    SHIFTIN PsxDat, PsxClk, LSBPOST, [psxJoyRX]
    SHIFTIN PsxDat, PsxClk, LSBPOST, [psxJoyRY]
    SHIFTIN PsxDat, PsxClk, LSBPOST, [psxJoyLX]
    GOSUB PSX_TxRx : psxJoyLY = psxIn
    HIGH PsxAtt ' deselect controller
    RETURN
    
    Move_Servos:
    '================Move Servos=================
          TimeUD = psxJoyRY */ ScaleY      'psxJoyRY = right joystick - Y axis = Up-Down
          TimeUD = TimeUD + Offset         'psxJoyRY = right joystick - Y axis = Up-Down
          TimeRL = psxJoyRX */ ScaleX      'psxJoyRX = right joystick - X axis = Left-right
          TimeRL = TimeRL + Offset         'psxJoyRX = right joystick - X axis = Left-right
    SELECT TimeUD                       'Deadzone to calm servos at neutral position
    CASE  113 TO 142
    GOTO Skip
    ENDSELECT
      PULSOUT UDServo, TimeUD               ' Send pulses to servo.
      PULSOUT RLServo, TimeRL
      PAUSE 18
    Skip:
    RETURN
    

    I added the Select-Case statement to introduce a Deadzone since the sticks do not return to the same value when released. This is an old controller so I will source a new one in the near future.
    I have servo movement that follows the two joysticks but it very jerky. The servos seems to overshoot the "target" and wiggle back and forth until they settle down to the intended location. I suppose that some of this is due to the nature of having to execute a lot of other code during the loop.

    Would the ServoPal be the ticket for eliminating this jittery servo movement by off-loading the servo control from the BS2 code loop? I've read the datasheet but am not quite sure how to implement the nlnp statementy. Is it as easy as adding the Initialization code and replacing the Move_Servos subroutine with the following to include the nInp code?

    Move_Servos:
    '================Move Servos=================
          TimeUD = psxJoyRY */ ScaleY      'psxJoyRY = right joystick - Y axis = Up-Down
          TimeUD = TimeUD + Offset         'psxJoyRY = right joystick - Y axis = Up-Down
          TimeRL = psxJoyRX */ ScaleX      'psxJoyRX = right joystick - X axis = Left-right
          TimeRL = TimeRL + Offset         'psxJoyRX = right joystick - X axis = Left-right
    SELECT TimeUD                       'Deadzone to calm servos at neutral position
    CASE  113 TO 142
    GOTO Skip
    ENDSELECT
        PULSOUT nInp, TimeUD                    ' Send pulses to servo.
        PULSOUT nInp, TimeRL                    ' Send pulses to servo.
        PAUSE 18
    Skip:
    RETURN
    
    

    falcon
Sign In or Register to comment.