Tuesday, February 17, 2009

Controlling Servo Motor Positions using Duration in Parallax Basic Stamp BS2

 

One of the problems I came across when attempting to control a servo motor was the position of motor horn. It is a well known fact that the servo motor need pulses for it to work. This is achieved by raising voltage on control pins (Hi), Making it Low (LO), and then, pausing for set amount of time, say , 20 ms. The “Raising” and Making “Low” can be achieved using the PULSOUT command. The syntax of PULSOUT command is as follows:

PULSOUT <pinNumber>, <Duration>

The Pin number is an obvious parameter (Doh!), but the Duration part is a bit tricky, because the unit of Duration is actually 2 micro Seconds (written as 2us from now on).

Hence, the following command:

                    PULSOUT 14, 1

Will result in getting a pulse to pin 14, with HIGH lasting for just 2us, and then becoming LOW. Lets see another example:

                    PULSOUT 14,1000

will result in getting a pulse to pin 14 with HIGH lasting for 1000*2us  = 2ms. The relevance of this duration discussion will become evident in just a second. Basically, it is this duration, that determines the positioning of a servo motor horn / amount of turn that the motor will do when its given control pulse. This pulse train needs to be sent to servo motor once in say 10 – 30 ms. Hence, to hold a motor on a particular location, we use FOR loops and PAUSE statements, as you will see in the example shortly.

For now, here is a diagram which gives an idea of durations and locations. This diagram was got from Parallax forums, where one of the best teacher, Andy Lindsay posted the information.

Servo Position Control WRT a Clock's Hour Hand

As you can see from the above diagram, to achieve a horn position of 12:00 O Clock, the following can be used, assuming the control pin is PIN 14:

PULSOUT 14, 750

Similarly a 9 O’Clock position –> PULSOUT 14, 1250

3 O’Clock Position –> PULSOUT 14, 250

As we can see, as the duration becomes higher than 750, the movement becomes counter clockwise. With duration lesser than 750 (which = 750* 2us = 1.5 ms ), the motor turns clockwise.

Now, with that “mystery” duration out of our way, lets see an example which will turn the servo motor Counter Clockwise, Clockwise, and then, to 12 O’Clock position. This is the program I came across when starting my robotics/electronics/microcontroller studies, and got utterly confused on how/why the servo motor was behaving as it was. The following program was available in the Microcontroller tutorial book by Parallax, written by Andy Lindsay. After the book was published, with many people having the same question, Andy Lindsay published an extra page on this topic in Parallax forum site. The following URL will take you there:

http://forums.parallax.com/forums/default.aspx?f=6&m=164400

Now, to the program:

********************************* Begining of program *******************

  counter VAR Word

DEBUG "counterclockwise 10 oclock", CR

FOR counter = 1 TO 150
   PULSOUT 14, 1000
   PAUSE 20
NEXT

DEBUG "clockwise 2 oclock", CR

FOR counter = 1 TO 150
   PULSOUT 14, 500
   PAUSE 20
NEXT

DEBUG "center 12 oclock", CR

FOR counter = 1 TO 150
  PULSOUT 14, 750
   PAUSE 20
NEXT

DEBUG "all done"

END

*********************************End Of Program *************************

The First Loop

DEBUG "counterclockwise 10 oclock", CR

FOR counter = 1 TO 150
   PULSOUT 14, 1000
   PAUSE 20
NEXT

First, the servo motor will get 150 pulse signal trains, each HI lasting for 1000 * 2us = 2ms duration. After each such signal, the PAUSE 20 will insert a delay of 20 milliseconds, and the loop continues. As per our discussion earlier, regarding the duration and location of servo motor horn, we understand that the servo horn should come somewhere near 10 O’Clock position. Once it reaches the position, the motor will hold that position for some time. Now, how much time does it hold that position? Lets find out…

Each loop has a pause of 20 ms. Also, each pulse last 2 ms. Hence, total delay in the loop = 20 ms (from PAUSE) + 2 ms (from duration of PULSOUT) = 22ms.

Hence, total time required to execute the first 150 loops
                                       = 22 * 150
                                       = 3300 milliseconds
                                       = 3.3 Seconds.

The Second Loop

DEBUG "clockwise 2 oclock", CR

FOR counter = 1 TO 150
   PULSOUT 14, 500
   PAUSE 20
NEXT

Now, lets consider the second loop. Here too, the servo motor will get a train of 150 pulses. But this time, the duration parameter is 500. This means that each pulse will last only 500 * 2us = 1ms.

From what we have seen in above duration/position explanation/diagram, we understand that the servo motor will move to a location somewhere near to 2 O’Clock position, and hold the position. Again… for how long? Lets find out:

Each loop as a pause of 20ms, because of the PAUSE command. Also, each pulse last 1 ms.

Total delay of loop = 20 ms (From PAUSE) + 1ms (from PULSOUT)
                            = 21 ms.

Total time required to execute 150 loops
                            =  21ms * 150
                            = 3150 milliseconds
                            = 3.1 Seconds.

I leave it to you to figure out how the 3rd and final loop works.

Food For Thought

Before concluding this post, let me discuss how to control the time for which the servo motor holds a position. Remember.. in real world though… we may be using an infinite loop to get input from say, a switch/sensor, to control the motor. But for this example, we can control the time and speed in which the motor moves by changing the number of loops and the PAUSE parameter. In the first loop, increasing the PAUSE duration will result in the servo motor getting to the intended position more slowly, and then holding the position.

However, if you want to motor to reach its position fast, and THEN hold the position, leave the PAUSE duration alone, but increase the number of loops. Think about it … :).