Simple Servo Position Control Program - Is this right?


Closed Thread
Results 1 to 11 of 11
  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,520


    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,520


    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,614


    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 " !!!
    *****************************************

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


    Did you find this post helpful? Yes | No

    Default Thanks!

    Alain,

    Thanks for that code. I had some of my own code that was partially working (servo would only go one direction) that I was in the lab troubleshooting right now. But, I think I might break your code down a little bit to where I'll have two buttons controlling the CW and CCW movement. That way I can make sure I fully understand the overall process of the code.

    Thanks again.

    -Marcus

  8. #8
    Join Date
    May 2010
    Location
    Chile
    Posts
    25


    Did you find this post helpful? Yes | No

    Default Re: Simple Servo Position Control Program - Is this right?

    I've made some code that might help you.
    It was for a high voltage SPDT servo switch for my research.

    It sends a 1 second burst signal to the servo and then release it.
    Usually thats more than enough time for the servo to react

    Code:
    '//ON INITIAL CONFIG
    A      VAR BYTE  'counter
    SerPos var word  'servo position variable
    
    sers var PORTB.0 'servo signal pin out
    
    '//ON MAIN PROGRAM ROUTINE
    '-Set servo position
    serpos = 1300 'uS   pulse width: 0 -> 1000uS / 180 -> 2000uS
    gosub servout 'send pulse for 1 second
    
    '//ON SUBROUTINES
    servOUT: 'sends servo a PWM position signal for 1 sec.
    for a = 0 to 59  '60hz
        Sers = 1
        pauseus serpos
        Sers = 0
        PAUSEUS 2000-serpos '2ms TOTAL
        pauseus 14667 '2+14.667ms = 16.667ms -> 60hz  -> 1seg total refresh time
    next a
    
    return
    "If at first doesn't work, kicking it wont help either"

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


    Did you find this post helpful? Yes | No

    Default Re: Simple Servo Position Control Program - Is this right?

    Not to bring up a dead subject, and I am not sure if anybody is going to have any interest in helping out. But if I am using a code similar to Alain's that he posted above ^^^, how can I slow down the movement of the servo? Basically, the servo goes straight from one point to another. I want to add something that will make it so that rather then jumping from position one to position two and back again that it takes, say 10 seconds, to gradually move from position one to position two. I have an idea in mind to basically have it move from say position 200 to 300 by 1 every .1 seconds so that after 10 seconds it has reached the second position. I would think a counting function or something would work so that it would go
    Code:
    IF I >= 50 THEN
    position=200
    pause 100
    position=201
    pause 100
    position=202
    pause 100
    ...
     ELSE 
      POSITION = 200
     ENDIF
    And if that is what it takes that I need to type out the whole process count down then so be it. But I would think there would be an easier option..

    Application: My problem right now is that there is a 4 inch piece of copper rod on the servo with a ceramic insulator attached to the end of that copper arm. So whenever it moves from position one to position two, the momentum of the mass of the ceramic insulator is causing the servo to overshoot its programmed position. Maybe its a servo issue, but I thought I would start with this.

    Any thoughts or help?
    Last edited by marcusvm; - 28th March 2011 at 04:51.

  10. #10
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,803


    Did you find this post helpful? Yes | No

    Default Re: Simple Servo Position Control Program - Is this right?

    Simple solution:

    Code:
    For position=start to finish
        pause 100 
        gosub Servo_Control
    Next position
    Ioannis

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


    Did you find this post helpful? Yes | No

    Default Re: Simple Servo Position Control Program - Is this right?

    Ioannis, would you mind explaining that code a little bit to me? I'm a bit of a newbie and haven't dealt with a lot of different code. Is it as simple as copy and pasting in ....

    Code:
    For position=start to finish
        pause 100 
        gosub Servo_Control
    Next position
    Or are there values for start and finish? and is
    Code:
    gosub Servo_Control
    another program loop? If so what for? Sorry if this is a simple code and I am being an idiot.

    Thanks.

    -Marcus

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