Share this

Robot Programming: Servo Motors of Robots

2026-04-06 04:33:05 · · #1

A robot's servo motor is a component used to convert motion commands from the robot's "brain" into actual movements, much like the muscles in a human. This lecture teaches you how to connect, adjust, and test robot servo motors. To do this, you need to understand and master the relevant PBASIC instructions and programming techniques for controlling the direction, speed, and timing of the servo motors. Since precise control of the servo motors is crucial to robot performance, familiarizing yourself with these concepts before installing the servo motors onto the robot chassis is essential.

Introduction to Continuous Rotary Servo Motor

There are many types of robot servo motors. This lecture will mainly introduce the continuous rotation servo motor that enables your wheeled robot's two wheels to rotate continuously, as shown in Figure 2-1. The figure shows the external accessories of this servo motor, which will be used in this lecture or subsequent chapters.

Task 1: Connect the servo motor to the teaching board

In this task, the servo motor is first connected to the power supply and the I/O port of the BASICStamp module. Then, an LED circuit is built to monitor the motion control signals sent to the servo motor by the BASICStamp module.

The following components are required for connecting the servo motors: two continuous rotary servo motors manufactured by Pallas Corporation; two sets of components for building the LED circuit (LEDs and 470-ohm resistors); and connecting the servo motors to the teaching base.

Turn the three-position switch to the 0 position to cut off the power to the teaching base (Figure 2-2).

Figure 2-3 shows the servo motor wiring terminals on the teaching board. You can use the jumpers on the board to select whether the servo motor's power supply comes from the battery box Vin in the robot kit or from an external DC power supply Vdd. To move the jumper cap, you must pull the jumper cap upwards off the two pins that were originally shorted, and then press the jumper cap into the two pins that you want to short.

If using a 6V battery pack, connect the jumper cap between the two servo motor terminals to Vin, as shown in Figure 2-3 (left).

If using a 7.5V, 1000mA DC power supply, connect the jumper cap to Vdd, as shown in Figure 2-3 (right figure).

All examples and instructions in this book are powered by a battery pack. Figure 2-4 is a schematic diagram of the circuit you will build, with the jumper set to Vin.

Note: Each servo motor's control cable has three wires: white for transmitting control signals, red for connecting to the power supply, and black for ground. These wire colors are defined at the servo motor's factory. You will later see in engineering projects that many electrical components use wire colors to indicate their function.

After the connection is completed, the system is shown in Figure 2-5 (excluding the LED monitoring circuit).

The LED monitoring circuit is shown in Figure 2-6. The left side is the electrical schematic, and the right side is the wiring diagram on the breadboard. This circuit can monitor and control the signals of the servo motor. Why?

As shown in the servo motor wiring diagram in Figure 2-4, the control signal lines (white) of the two servo motors are connected to the P12 and P13 ports of the microcontroller, respectively. That is, the control signals output from the P12 and P13 ports of the microcontroller control the movement of the two servo motors. The LED monitoring indicator circuit shown in Figure 2-6 also indicates the signals of the P12 and P13 ports. Therefore, the LED circuit in Figure 2-6 can monitor the control signals of the servo motors.

Task 2: Zeroing the servo motor

Servo motor zeroing refers to the process of keeping the servo motor stationary when a specific control signal (zero-point calibration signal) is sent to it. Since servo motors are not pre-calibrated at the factory, they may rotate upon receiving the zero-point calibration signal. Therefore, you need to use a screwdriver to adjust the regulating resistor within the servo motor module to keep the motor stationary. This is the servo motor zeroing process. After adjustment, you need to test the servo motor to verify its functionality. The test program will send control signals to make the servo motor rotate clockwise and counterclockwise at different speeds.

Zeroing tool

The screwdriver provided in the robot kit is the only additional tool needed for this task.

Send zero-point calibration signal

The signal shown in Figure 2-7 is the zero-point calibration signal sent to the servo motor connected to P12. This signal is called the zero-point calibration signal. If the servo motor's zero point has been properly adjusted, sending this signal to the motor will keep it stationary. It is a pulse sequence signal with a pulse interval of 20ms and a pulse width of 1.5ms.

To enable the robot's brain, the BS2 microcontroller, to generate the zero-point calibration signal shown in Figure 2-7, several new PABSIC instructions must be used: the PULSOUT instruction, the PAUSE instruction, and the DO…LOOP loop statement.

The PULSOUT instruction is used to make the microcontroller generate a 5V level pulse. Its instruction format and parameters are as follows:

The `PULSOUTPin,Duration` command parameter `Pin` determines which I/O pin of the microcontroller to output the pulse to, while `Duration` determines the pulse width in 2 microseconds. Therefore, to generate a 1.5ms high-level pulse signal as shown in Figure 2-7 for pin P12, the following command line needs to be entered:

PULSOUT 12,750

Obviously, if you know the pulse duration, you can easily calculate the value of the Duration parameter in the PULSOUT instruction: Duration variable = pulse duration / 2 microseconds. Following this formula, the width variable of the zero-point calibration pulse is:

Duration=0.0015s/0.000002s=750.

The PULSOUT instruction only generates pulses; to control the interval between pulses, the PAUSE instruction in the PBASIC language must be used.

The usage format of the PAUSE directive is as follows:

PAUSEDuration is a parameter of the PAUSE instruction. Its value tells the BASICStamp microcontroller how long to wait before executing the next instruction. The unit of Duration is one-thousandth of a second, or milliseconds. If you want to wait for 1 second, you can assign a value of 1000 to Duration.

The instructions are as follows:

PAUSE1000

If you want to wait 2 seconds, it means the following:

Therefore, to achieve the zero-point calibration signal shown in Figure 2-7, the following statement must be added after the PULSOUT command:

PAUSE20

To continuously generate the pulse sequence signal shown in Figure 2-7, the PULSOUT and PAUSE statements must be placed within the DO…LOOP loop. For computers or microcontrollers, which act as the brain of robots, one of their greatest advantages compared to the brains of humans or other organisms is their ability to repeatedly perform the same task without complaint. If you want your microcontroller to continuously repeat the same operation, simply place the relevant instructions between the instruction keywords DO and LOOP. Therefore, to make the microcontroller continuously generate zero-point calibration signals, simply place the PULSOUT and PAUSE statements between DO and LOOP. The program module that can finally generate the zero-point calibration signal shown in Figure 2-7 is as follows:

Example: CenterServoP12.bs2

'CenterServoP12.bs2

'Thisprogramsends1.5mspulsestotheservoconnectedto

'P12formanualcentering.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

DO

PULSOUT 12,750

PAUSE20

LOOP

Note: Once the above program is executed, it will continue indefinitely until you turn off the power to the microcontroller. The next task will guide you on how to control the number of times it is repeated.

It's best to calibrate only one motor at a time, because this way you can hear (why hear, not see?) when the motor stops while you're adjusting it. The procedure above only sends the zero-point calibration signal to P12. The following steps will guide you on how to adjust the motor to keep it stationary. After adjusting the servo motor connected to P12, adjust the motor connected to port P13 using the same method.

Turn the three-position switch on the teaching base to "2" and turn on the power.

Enter, save, and run the program CenterServoP12.bs2.

If the motor is not zero-point calibrated, its connecting throat will rotate, and you can hear the motor running inside.

If the motor has not yet been zero-point calibrated, follow the steps shown in Figure 2-8 to gently adjust the potentiometer on the servo motor with a screwdriver until the motor stops rotating. (Listen carefully to the motor sound to confirm that it has stopped rotating.)

Verify whether the LED in the signal monitoring circuit connected to P12 is lit. If it is lit, it indicates that the zero-point calibration pulse has been sent to the motor connected to the P12 port.

If the motor has already completed zero-point adjustment, it will not turn. However, a damaged or faulty motor may also not turn. Task 4 will eliminate this possibility before installing the motor onto the robot chassis.

If the motor does stop turning, you can test the servo motor connected to P13 and perform zero-point calibration yourself.

It's your turn to perform zero-point adjustment on the servo motor connected to the P13.

Repeat the above process for the servo motor connected to P13 using the following procedure:

Program example: CenterServoP13.bs2

'CenterServoP13.bs2

'Thisprogramsends1.5mspulsestotheservoconnectedto

'P13formanualcentering.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

DO

PULSOUT 13,750

PAUSE20

LOOP

Note: If you do not intend to perform any further tasks after completing the above tasks, be sure to disconnect the power supply to the teaching board.

Task 3: How to save numerical values ​​and counts

In Task 2, you learned how to use loop statements to make the microcontroller continuously generate zero-point calibration signals. Of course, when writing a program, you don't always need the robot to perform the same operation or task forever, but only want it to execute for a specified time or a fixed number of times. In this case, you'll need to use variables in your PBASIC program.

Variables are used to store numerical values. Subsequent robot programming relies heavily on the use of variables. The primary purpose of using variables to store numerical values ​​is to allow the program to count. Once your program can count, you can control and track the number of times events occur.

Variables are used to store numerical values; mathematical operations and counting variables can be used to store numerical values. In the PBASIC language, before using a variable, you must first give it a name and specify its type. This is called declaring a variable. The PBASIC syntax for declaring a variable is as follows:

variableNameVARSize

When actually declaring a variable, you use your own name instead of variableName. Size is used to specify the size and type of the variable. The variable types that can be declared in a PBASIC program are as follows:

Bit — stores 0 or 1;

Bib — used to store any value between 0 and 15;

Byte — used to store any value between 0 and 255;

Word—used to store any value between 0 and 65535, or any value between -32768 and 32767.

Note: Why are there specific variable types and sizes mentioned above? Please refer to the explanation of binary.

The following routine contains two variables of size "word":

valueVARWord

anotherValueVARWord

After declaring a variable, you can also initialize it, that is, give it an initial value.

value=500

anotherValue=2000

In "value=500", the symbol "=" is an operator. You can use other operators and variables to perform mathematical operations. Here are two examples of multiplication:

value = 10 * value

anotherValue = 2 * value

Program example: VariablesAndSimpleMath.bs2

This routine demonstrates how to declare, initialize, and perform operations on variables.

Predict what the DEBUG command will display before running the program.

Enter, save, and run the program VariablesAndSimpleMath.bs2.

Compare this to your prediction and explain why all the discrepancies are different.

'VariablesAndSimpleMath.bs2

'Declarevariablesandusethemtosolvewarithmeticproblems.

'{$STAMPBS2}

'{$PBASIC2.5}

valueVARWord'Declarevariables

anotherValueVARWord

value=500'Initializevariables

anotherValue=2000

DEBUG?value'Displayvalues

DEBUG?anotherValue

value=10*anotherValue'Performoperations

DEBUG?value'Displayvaluesagain

DEBUG?anotherValue

END

How does the program VariablesAndSimpleMath.bs2 work?

The code below defines two word variables: value and anotherValue.

valueVARWord'Declarevariables

anotherValueVARWord

Then, initialize the variables, that is, assign the variables you just declared with the initial values ​​you decide. After these two instructions are executed, the value of value is 500, and the value of anotherValue is 2000.

value=500'Initializevariables

anotherValue=2000

The subsequent DEBUG command helps you understand the value stored in each variable after initialization, since the value assigned to `value` is 500.

The `anotherValue` instruction is assigned the value 2000, therefore the `DEBUG` instruction sends the messages "value=500" and "anotherValue" to the debug terminal.

=2000” and display it.

DEBUG?value'Displayvalues

DEBUG?anotherValue

Here, a new format specifier character "?" is introduced for the DEBUG command. This character is placed before a variable name to make the DEBUG terminal display the name and the value stored in that variable, followed by pressing Enter. This makes it very convenient to query the contents of a variable.

The question in the following three lines is: What will the debug terminal display? The answer is that the value of `value` is 10 times that of `anotherValue`, because the value of `anotherValue` is 2000, so `value` is 20000, while the variable `anotherValue` remains unchanged.

value=10*anotherValue'Performoperations

DEBUG?value'Displayvaluesagain

DEBUG?anotherValue

Your turn—calculate using negative numbers.

If you want to perform calculations involving negative numbers, you can use the SDEC format specification of the DEBUG command to display them. The following example can be obtained by modifying the program VariablesAndSimpleMath.bs2.

Delete the following part of the program VariablesAndSimpleMath.bs2:

value=10*anotherValue'Performoperations

DEBUG?value'Displayvaluesagain

Change it to the following code:

value=value-anotherValue'Answer=-1500

DEBUG"value=",SDECvalue,CR'Displayvaluesagain

Run the modified program and verify that the value has changed from 500 to -1500.

The most convenient way to count and control the number of times a piece of code is executed is to use a FOR…NEXT loop, with the following syntax:

FORCounter = StartValue TO EndValue {STEP StepValue} … NEXT The ellipsis “…” indicates that you can place one or more program instructions between FOR and NEXT. Before using the preceding loop, ensure that a variable is declared to replace the parameter Counter. The parameters StartValue and EndValue can be numbers or variables. The content enclosed in curly braces {} in the syntax description indicates optional parameters. In other words, FOR…NEXT will still work without it, but you can use it for some special purposes.

You don't necessarily have to name the variable "counter"; for example, you can use "myCounter".

myCounterVARWord

Below is a FOR…NEXT loop routine that uses myCounter to count. Each time the loop executes, it displays...

The value of myCounter.

Example: CountToTen.bs2

Enter, save, and run the program CountToTen.bs2.

'CountToTen.bs2

'UseavariableinaFOR...NEXTloop.

'{$STAMPBS2}

'{$PBASIC2.5}

myCounterVARWord

FORmyCounter=1TO10

DEBUG?myCounter

PAUSE500

NEXT

DEBUGCR, "All done!"

END

Your turn—different initial and final values ​​and counting step sizes.

You can assign different values ​​to the variables StartValue and EndValue.

Modify the FOR…NEXT loop as follows:

FORmyCounter=21TO9

DEBUG?myCounter

PAUSE500

NEXT

Run the modified program. Did you notice that BASICStamp now counts downwards instead of upwards? The program will run this way as long as StartValue is greater than EndValue.

Remember the optional parameter {STEPStepValue}? You can use it to make myCounter count with different step sizes, instead of incrementing by 1 each time like 9, 10, 11… For example, you can make it increment by 2 (9, 11, 13…) or by 5 (10, 15, 20…) or any StepValue you give, either incrementing or decrementing. The example below counts downwards with a step size of 3.

Add STEP3 to the FOR…NEXT loop as follows:

FORmyCounter=21TO9STEP3

DEBUG?myCounter

PAUSE500

NEXT

Run the modified program to verify that it decreases in increments of 3.

Task 4: Test the servo motor

Before assembling the robot, there's one last thing to do: test the servo motors. In this task, you'll run a program to make the motors rotate at different speeds and directions. This testing ensures the motors are functioning correctly before assembly.

This is an example of subsystem testing. Testing subsystems is a good practice in the development process; it's not just about taking the robot apart, but about fixing potential problems as much as possible before assembling it.

Subsystem testing is the process of testing individual components before assembling them into a larger device. This is invaluable in robotics competitions. For engineers, whether developing toys, cars, video games, or space shuttles and Mars rovers, it's a fundamental skill. Especially with highly complex devices, identifying problems without prior subsystem testing is nearly impossible. For example, in space projects, disassembling a prototype for repair can cost millions of dollars. Therefore, in such projects, thorough and rigorous testing of all subsystems is essential.

Pulse width control controls the speed and direction of the motor.

Recall the motor zero-point calibration mentioned earlier. A control signal with a pulse width of 1.5ms kept the motor stationary, achieved by assigning a value of 750 to the Duration parameter of the PULSOUT command. So, what would happen if the pulse width of the control signal was not 1.5ms?

The program now sends a series of 1.3ms pulses to the servo motor. Examine this series of pulses carefully and see how it controls the motor. Figure 2-9 shows the continuous rotary motor rotating clockwise at full speed, which is approximately 50 to 60 revolutions per minute (RPM), or about one revolution per second.

You can use the following program

ServoP13Clockwise.bs2 will send these pulses

The sequence is sent to port P13.

Example: ServoP13Clockwise.bs2

Enter, save, and run the program ServoP13Clockwise.bs2.

Verify that the motor's output shaft rotates clockwise at a speed between 50 and 60 RPM.

'ServoP13Clockwise.bs2

'RuntheservoconnectedtoP13atfullspeedclockwise.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

DO

PULSOUT 13,650

PAUSE20

LOOP

Note: A 1.3ms pulse requires the Duration parameter of the PULSOUT command to have a value of 650, which is a number less than 750. All pulse widths must be less than 1.5ms, meaning the Duration parameter of the PULSOUT command must be less than 750, for the motor to rotate clockwise.

Of course, when performing the above verification, the servo motor must be connected to the control port and the power supply must be plugged in.

Example: In ServoP12Clockwise.bs2, changing the PIN parameter of the PULSOUT instruction from 13 to 12 will cause the motor connected to P12 to rotate clockwise at full speed.

Save the program ServoP13Clockwise.bs2 as ServoP12Clockwise.bs2.

Change the value of the PIN parameter of the PULSOUT instruction from 13 to 12 and update the comments.

Run the program to verify that the motor connected to P12 is rotating clockwise and at a speed between 50 and 60 RPM.

'ServoP12Clockwise.bs2

'RuntheservoconnectedtoP12atfullspeedclockwise.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

DO

PULSOUT 12,650

PAUSE20

LOOP

Example: ServoP12Counterclockwise.bs2

You might have guessed that the Duration parameter of the PULSOUT command should be set to a number greater than 750.

This will cause the servo motor to rotate counterclockwise.

A Duration value of 850 can generate a pulse with a width of 1.7ms, as shown in Figure 2-10, which will cause the servo motor to rotate counterclockwise at full speed.

Save the program ServoP12Clockwise.bs2 as ServoP12Counterclockwise.bs2 and change the Duration parameter of the PULSOUT instruction to 850.

Run the program to verify that the motor connected to P12 is rotating counterclockwise and at a speed between 50 and 60 RPM.

'ServoP12Counterclockwise.bs2

'RuntheservoconnectedtoP12atfullspeedcounterclockwise.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

DO

PULSOUT 12,850

PAUSE20

LOOP

Your turn.

Modify the PIN parameter of the PULSOUT instruction in the above example to make the motor connected to P13 rotate counterclockwise.

Example: ServosP13CcwP12Cw.bs2

You can use two PULSOUT commands to make two servo motors rotate simultaneously, or you can make them rotate in opposite directions.

Enter, save, and run the following program: ServosP13CcwP12Cw.bs2.

Run the program to verify that the motor connected to P13 rotates counterclockwise at full speed, while the motor connected to P12 rotates clockwise at full speed.

'ServosP13CcwP12Cw.bs2

'RuntheservoconnectedtoP13atfullspeedcounterclockwise

'andtheservoconnectedtoP12atfullspeedclockwise.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

DO

PULSOUT 13,850

PULSOUT 12,650

PAUSE20

LOOP

The following understanding is very important. Think about it: if motors are mounted on both sides of a robot's chassis, one rotating clockwise and the other counterclockwise, the robot will move in a straight line. Does that sound a bit strange? If you don't understand, try this:

Place the two motors back-to-back and run the program again.

Your turn—adjust your speed and direction.

When both motors are rotating at full speed, the Duration parameter of the two PULSOUT commands has four different combinations. These combinations will be frequently used when programming robot motion in later chapters. The program ServosP13CcwP12Cw.bs2 sends one of these combinations: 850 to P13 and 650 to P12. By testing different motion combinations and filling in the motion description column of Table 2-1, you will gradually become familiar with these combinations and build a reference for yourself. After the robot is assembled, try these motion combinations and fill in the motion behavior column of the table below. You will then see how each data combination makes it move.

Try the following PULSOUTDuration combination and fill in the results in the description column.

FOR…NEXT Cyclic control of motor running time

By now, you fully understand the principle of pulse width modulation (PWM) for controlling the speed and direction of a continuously rotating motor. Controlling the motor's speed and direction is very simple, and there's also a simple way to control the duration of the motor's operation: using...

FOR…NEXT loop.

Below is an example of a FOR…NEXT loop that will make the motor run for a few seconds.

FORCOUNTER=1TO100

PULSOUT 13,850

PAUSE20

NEXT

Calculate the exact time this code will make the motor rotate. Each loop iteration involves a PULSOUT instruction lasting 1.7ms and a PAUSE instruction lasting 20ms. Each loop iteration takes approximately an additional 1.3ms. Therefore, the total execution time of the FOR…NEXT loop is: 1.7ms + 20ms + 1.3ms = 23.0ms. If this loop executes 100 times, that's 23.0ms multiplied by 100, which equals 100 * 23.0 milliseconds = 100 * 0.023 seconds = 2.3 seconds.

If you want the motor to run for 4.6 seconds, the FOR…NEXT loop must be executed twice as many times as above. FORcounter=1TO200

PULSOUT 13,850

PAUSE20

NEXT

Example: ControlServoRunTimes.bs2

Enter, save, and run the program ControlServoRunTimes.bs2.

To verify whether the motor connected to P13 is rotated counterclockwise for 2.3 seconds, the motor connected to P12 is rotated for 4.6 seconds.

'ControlServoRunTimes.bs2

'RuntheP13servoatfullspeedcounterclockwisefor2.3s,then

'runtheP12servofortwiceaslong.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

counterVARByte

FORcounter=1TO100

PULSOUT 13,850

PAUSE20

NEXT

FORcounter=1TO200

PULSOUT 12,850

PAUSE20

NEXT

END

If you want both motors to run simultaneously, send an 850 pulse width to the motor connected to P13 and send an 850 pulse width to the motor connected to P12.

With a pulse width of 650, the time required to execute one loop is:

1.7ms – Motor connected to P13

1.3ms – Motor connected to P12

20ms – Interrupt duration

1.6ms – Code execution time

---------------------------------------

It took a total of 24.6ms.

If you want the motor to run for a specific period of time, you can calculate the number of cycles required (or the number of pulses needed).

(Quantity) is as follows:

Number of pulses = Time / 0.0246 seconds = Time / 0.0246

If you want the motor to run for 3 seconds, the calculation is as follows:

Number of pulses = 3 / 0.0246 = 122

Now, you can set the value of EndValue in the FOR…NEXT loop to 122, as shown in the following code:

FORcounter=1TO122

PULSOUT 13,850

PULSOUT 12,650

PAUSE20

NEXT

Example: BothServosThreeSeconds.bs2

The following program is an example of making two motors rotate in one direction for 3 seconds, and then in the opposite direction for 3 seconds.

Enter, save, and run the program BothServosThreeSeconds.bs2.

'BothServosThreeSeconds.bs2

'Runbothservosinoppositedirectionsforthreeseconds,thenreverse

'the direction of bothservosandrunanotherthreeseconds.

'{$STAMPBS2}

'{$PBASIC2.5}

DEBUG "ProgramRunning!"

counterVARByte

FORcounter=1TO122

PULSOUT 13,850

PULSOUT 12,650

PAUSE20

NEXT

FORcounter=1TO122

PULSOUT 13,650

PULSOUT 12,850

PAUSE20

NEXT

END

Verify that each motor runs in one direction for 3 seconds and then in the opposite direction for 3 seconds. Have you noticed that when the motors run in opposite directions simultaneously, they always maintain the opposite direction? What is the purpose of this?

Your turn – Estimate motor running time: Set a desired running time for the motors. Divide the time by 0.024 to get the number of loops you need to execute. Modify the program BothServosThreeSeconds.bs2 to make both motors run for the set time. Compare the estimated time with the actual running time. Remember to disconnect the system power after completing the experiment. Engineering skills and knowledge summarized include: wiring diagrams and wiring of Pallas servo motors; monitoring circuits and circuit construction for servo motor control signals; zero-point calibration of servo motors and the use of PULSOUT, PAUSE, and loops; use of PABSIC variables and control of loop count; motor testing and subsystem testing; simultaneous movement of two motors and control of movement time, etc.

Read next

CATDOLL 126CM Sasha

Height: 126cm Weight: 23kg Shoulder Width: 32cm Bust/Waist/Hip: 61/58/66cm Oral Depth: 3-5cm Vaginal Depth: 3-15cm Anal...

Articles 2026-02-22