Simple Servo Position Control Program - Is this right?


Closed Thread
Results 1 to 11 of 11

Hybrid View

  1. #1
    Join Date
    Oct 2010
    Location
    Northern Colorado
    Posts
    19

    Default Simple Servo Position Control Program - Is this right?

    I have a pretty simple process that I need carried out via a 16F88 and a servo.

    I have an arm that has a heating element on the tip of it. I need this heating element to be lowered onto a bed of grass for one second, then lifted out of the grass. I am testing the flammability of grass within a climate controlled wind tunnel. I want this to be triggered from a simple push of a NO button, then have it carry out the whole process from there. Problem is that I have not messed with a servo motor before and I am not sure if I am controlled it in the correct way. The button is on A0 and the servo control output would be on A1. What I have for code is

    Code:
    'Set internal clock settings for 16F88
    Define OSC 8
    OSCCON.4=1
    OSCCON.5=1
    OSCCON.6=1
    
    'Turn off A/D conversion
    ANSEL=0
    
    
    'Define variables and pins
    I	        VAR 	BYTE
    BUTTON		VAR	PORTA.0
    SERVO		VAR	PORTA.1
    
    'Continuous loop until triggered by ignition button
    buttonloop:
    
    If (BUTTON=0) Then goto buttonloop
    	Pause 10
    
    If (BUTTON=1) Then goto positionloop
    
    goto button loop
    
    'Servo position control loop
    positionloop:
    
    Pulsout PORTA.1, 100		'pulse to servo for a length of 1 ms to rotate servo CCW certain number of degrees
    For I=1 TO 100			'pulse to servo every 10 ms for a total of 1 second
    	Pause 1000
    NEXT
    
    Pulsout PORTA.1, 150		'pulse to servo for a length of 1.5 ms to move to "zeroed" position
    
    goto buttonloop
    
    End 				'end of program never reached
    Is this the correct way of doing it? Any help/suggestions would be great!

    -Marcus
    Last edited by marcusvm; - 22nd December 2010 at 19:41.

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default

    Hi,
    You need to provide the servo with pulses continously if you want it to "hold position", usually at a frequency of 50hz. In your application though it sounds like it would be enough to have it move to position and then "release" it. However, it's still not enough to just give it a single pulse.

    There are a couple of problems with your code
    Code:
    Pulsout PORTA.1, 100		'pulse to servo for a length of 1 ms to rotate servo CCW certain number of degrees
    For I=1 TO 100			'pulse to servo every 10 ms for a total of 1 second
    	Pause 1000
    NEXT
    This will only send a single a pulse to servo because the Pulsout is outside of the for next-loop. On top of that you are pausing 1000ms (1 second) each time thru the loop. I'd try something like:
    Code:
    For I = 0 to 100
     Pulsout PortA.1, 100
     Pause 19              'Pause 19ms for a total of 20ms which is 50Hz
    NEXT
    You have the same problem when trying to move the servo back to "zero". You only send a single pulse when you need to send it several in order to move it to position (and keep sending them at 50Hz) to "guarentee" that it stays there.

    /Henrik.

  3. #3
    Join Date
    Oct 2010
    Location
    Northern Colorado
    Posts
    19


    Did you find this post helpful? Yes | No

    Default Sweet!

    This will only send a single a pulse to servo because the Pulsout is outside of the for next-loop. On top of that you are pausing 1000ms (1 second) each time thru the loop. I'd try something like:
    Code:

    For I = 0 to 100
    Pulsout PortA.1, 100
    Pause 19 'Pause 19ms for a total of 20ms which is 50Hz
    NEXT
    Thanks for the help. That makes sense now that I think about it. The timing of it was probably the biggest problem I was having.

    With moving the servo back to its "zeroed" position- I was thinking that if I send it one pulse to lift it up at the end of the one second test, so that it doesn't sit there until it decides to return to its "zeroed" position on its own. So, with the one pulse I send it at the end, I am helping the servo return to its natural "zeroed" position. Does that make sense?

    I am going to do the programing and wiring here in a bit and play with the actual position of the servo in relation to the pulse width. Hopefully all goes smoothly.

    -Marcus

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default

    Does that make sense?
    Yeah, kind of. But it won't work if the mechanical load on the servo doesn't happen to be exactly as much as is needed to "coast" back to "zero" with the help of a single pulse.....

    I'm pretty sure the servo won't decide to move anywhere on its own. It might move due to external load on it if you don't "refresh" it continously though.

    So, when you're moving it back to "zero", do something similar to when you're moving into position, ie. pulse it at least enough times to make sure it reaches position.

    Good luck!

  5. #5
    Join Date
    Oct 2010
    Location
    Northern Colorado
    Posts
    19


    Did you find this post helpful? Yes | No

    Default Makes sense...

    Ok. I wasn't thinking about the load on the servo. What I think I'll do then is put the pulse that controls the "zero" position in the loop that is waiting for the button to be pressed (so that it is "zeroed" when button is NO), then have the movement pulse in the second loop.


    Code:
    'Continuous loop until triggered by ignition button
    buttonloop:
    	
    Pulsout PORTA.1, 150			'pulse to servo for a length of 1.5 ms to move to "zeroed" position
    
    If (BUTTON=0) Then goto buttonloop
    	Pause 10
    
    If (BUTTON=1) Then goto positionloop
    
    goto button loop
    
    'Servo position control loop
    
    positionloop:
    
    		
    FOR I=1 TO 100
    	Pulsout PORTA.1, 100		'pulse to servo for a length of 1 ms to rotate servo CCW certain number of degrees		
    	Pause 19			'pulse to servo every 10 ms for a total of 1 second
    NEXT
    
    goto buttonloop
    
    End 					'end of program never reached

    Thanks!

  6. #6
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Hi, Marcus

    this one should work as desired ...

    Code:
    '****************************************************************
    '*  Name    : GrassBurner.BAS                                   *
    '*  Author  : Acetronics                                        *
    '*  Notice  : Copyright (c) 2010                              *
    '*          : All Rights Reserved                               *
    '*  Date    : 23/12/2010                                        *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :                                                   *
    '****************************************************************
    '
    @ __config _CONFIG1, _INTRC_IO & _WDT_ON & _LVP_OFF & _CP_OFF
    ' DEFINES
    Define OSC 8
    Define BUTTON_PAUSE 0
    ' Internal Osc 8Mhz
    OSCCON = %01110010
    ' Turn off A/D conversion - Digital Inputs
    ADCON0 = 0
    ANSEL = 0
    ' Comparators Off
    CMCON  = 7
     
    'Define variables and pins
    I         VAR BYTE
    Position var WORD
    Delay  var Byte
    OldButton  var bit
    PORTA  = 0
    TRISA   = %11111101
    BUTTON_  VAR PORTA.0
    SERVO  VAR PORTA.1
     
    buttonloop:     ' Button check loop
     OldButton = 0
     LOW Servo
     Pulsout SERVO, 300  ' pulse to place servo to neutral
     Pause 19
     
    BUTTON BUTTON_,1,255,0,Delay,0,Buttonloop
     OldButton = 1       ' Launched ... We've pressed it !!!
    '******************************************************************************
    positionloop:  'Servo position control loop
     
    I = 0       ' Reset time counter
    While ( OldButton  AND ( I < 75 ))   '  if button has been pushed and time < 1.5s
     
     IF I >= 50 THEN     ' 1 second is ... 50 x 20 ms !    
      position = 300
     ELSE 
      POSITION = 200
     ENDIF 
     
     LOW Servo
     Pulsout SERVO, Position  ' pulse to servo 
     
     PAUSEUs 19813 - ( Position * 5 )        ' time between pulses
     
     I = I+1                         'Increase Time counter
    Wend                                ' go for seeking a new button push ...
     
    goto buttonloop
    End         'end of program supposed never reached
    may be you'll have to modify a bit the " @ __config ......" line if you use PM as an assembler.

    Also correct " IF I >= 50 ..." to i.e. " IF I >= 55 " to take servo positionning time into account ... knowing 1 unit is 20 ms.

    Alain
    Last edited by Acetronics2; - 23rd December 2010 at 13:17.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

Members who have read this thread : 1

You do not have permission to view the list of names.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts