Fads to Obsessions and Beyond...

Free domain for life, exceptional technical support, website transfer

SG-90 Servo Motor

A TowerPro SG-90 servo motor is interfaced with a PIC18F248 microcontroller to test digital control and operation of a servo motor.

A light seeking circuit that controls the servo motor to face sensors at the brightest light source (e.g. possible use case in aligning solar cells with the sun throughout the day) is also demonstrated.

In many situations a project will need to incorporate the ability to mechanically control the linear and or angular position of a component such as a valve, switch, wheel, RC aircraft aileron/rudder or other such physical device. A stepper motor could be used in many such applications. The stepper motor consumes power to move to and hold the commanded position. However, a servomotor only consumes power as it rotates to the user input position and then rests when this position is achieved.

A further disadvantage of a stepper motor is that upon power-up seperate control/hardware is required to obtain a known start position (e.g. the stepper motor needs to initially rotate until a limit-switch or similar is activated). A servomotor will immediately turn to whatever angle the firmware/hardware commands, regardless of the initial position upon power up.

The lack of feedback of a stepper motor limits its performance, as the stepper motor can only drive a load that is well within its capacity, otherwise missed steps under load may lead to positioning errors and the system may have to be restarted or recalibrated. The encoder and controller of a servomotor are an additional cost, but they optimise the performance of the overall system (for all of speed, power and accuracy) relative to the capacity of the basic motor. With larger systems, where a powerful motor represents an increasing proportion of the system cost, servomotors have the advantage (1).

A servomotor also only requires a single control line (in addition to the power and ground connections). The slight complication is the control signal is a pulse width modulated (PWM) waveform with particular requirements as to duty cycle and frequency. Although arguably stepper motor control, due to the multiple voltage/ground connections that must be switched in the correct sequence, is just as "complicated". The following is a brief overview of servomotor operation and control explaining the PWM requirement.

Servomotor Operation

A servomotor consists of the combination of a DC motor, a potentiometer, and the control circuit all within a "single package". The DC motor within the servomotor package is attached by gears to the output shaft and a potentiometer. As the motor rotates, the potentiometer's resistance changes, so the control circuit can precisely regulate how much movement there is and in which direction. When the shaft of the motor is at the desired position, the servomotor control circuit stops power to the DC motor. Otherwise, the DC motor is turned in the appropriate direction.

The desired position is sent via PWM pulses to the signal wire (the duty cycle of the PWM sets the position). The motor's speed is proportional to the difference between its actual position and desired position. So if the motor is near the desired position, it will turn slowly, otherwise it will turn fast (i.e., proportional control). Diagram 1 depicts the required PWM signal for the SG-90 as per the datasheet.

Diagram 1: SG90 PWM control signal

SG90 control signals

The Circuit Details and Schematic Diagrams Sections provide information about physical connection of the SG90 servo motor to a circuit to enable control with a PIC18F248 microcontroller.

The Testing/Experimental Results Section discusses the various steps used in testing the TowerPro SG-90 and examining the capability of the servomotor (precision and accuracy of angular position, torque etc). Also demonstrated is how to use the servomotor to control the position of a platform to point to the brightest light source using light dependant resistors as the sensors. This application is an example practical solution for pointing solar cells to maximise sun position and hence voltage/current.

The circuit consists largely of the usual minimum requirements for a PIC (PIC18F248 dealt with here) that is, power supply, oscillator (external crystal oscillator - 24MHz) and in-circuit serial programming (ICSP). A voltage reference is formed by the TL431 programmable shunt regulator diode.

The majority of the circuit is based upon the DIY PIC Development Board.

Circuit Operation

A "wall wart" power supply was chosen rather than constructing a dedicated DC power supply dropping/converting from an AC wall socket. Surplus chargers from laptops are readily available (in this case supplying 16-24V with 65W max) which provide not only a safer option (compared to construction from a suitable transformer, rectifier, connection to AC etc) but also a much more economical option (generally zero cost for a surplus charger, compared to ten's of dollars for a suitable transformer, let alone cost of ancillary circuitry, PCB etc).

The surplus laptop charger requires a suitable socket connection and a voltage regulator, in this case a LM317T, to provide the regulated 5V generally required by PIC microcontrollers. The power supply circuit is given in the Schematics Section. The LM317T circuit is the standard design direct from the datasheet, with input and output capacitors to provide smoothing and the resistor/potentiometer to provide selection of output voltage.

A TL431 programmable shunt regulator diode is used to provide a 5V reference for the PIC ADC module.

A MAX232 is used to enable RS-232 communication between the PIC microcontroller and an attached PC, in order to provide a means of starting/stop the servomotor, varying the pulse-width and similar functionality (rather than using buttons or similar).

Light Sensing/Tracking

Two light dependant resistors (LDR), in conjunction with 1K resistors forming voltage dividers, are used to sense light levels via voltage sensing using the PIC analog digital convertor (ADC) peripheral. The LDR's are mounted (see the Construction Notes/Trouble Shooting Section) in such a manner that an incident light beam cannot fall directly upon both LDR's simultaneously unless the LDR's are both perpendicular to the light beam.

The differential signal from the LDR's is therefore used to control the servomotor to move a platform holding the LDR's in order to reduce the LRD voltage differential below the desired threshold (and thus track the brightest incident light source). The firmware for reading the voltage from the LDR's is the same as described and detailed in the PIC analog to digital converter (ADC) page.


The firmware enables connection of the PIC18F248 with a PC via RS-232 and therefore control of the servomotor via keyboard commands. The firmware provides the necessary control of the PWM signal and reading of the light-dependant resistors (LDR's) etc. The firmware in terms of the reading the voltage across the LDR's is the same as described and detailed in the PIC analog to digital converter (ADC) page.

Pulse Width Modulated Signal

As briefly discussed in the Project Background Section, the SG-90 servomotor requires a PWM signal of 50Hz frequency with a variable duty cycle (nominally 1ms to 2ms). There are various methods of producing such a PWM signal, but since using a PIC18F248 for testing the SG-90, the microcontroller onboard peripherals were used.

The PIC18F248 has a PWM module which notionally would make using the SG-90 straight-forward. However, with a PIC oscillator frequency of 24MHz, the slowest possible PWM frequency using the PIC18F248 PWM peripheral is ~1.4kHz.

Using a slower oscillator speed is just "wasting" processing power of the PIC18F248, so in this case one of the PIC18F248 16-bit onboard timers is used to "manually" generate a PWM signal via an interrupt routine. This enables the PIC hardware to predominately handle the PWM signal, maximising the number of instruction cycles for other firmware use.

In order to produce the PWM signal, the PIC timer interrupt routine consists of initially driving the desired output pin high for the desired amount of time (nominally 1ms as a minimum for the -90o servomotor position, to a maximum of 2ms for the +90o position), and then holding the output pin low for the necessary remaining time to complete the PWM period (for a total of 20ms, i.e., 50Hz) - see Diagram 1 in the Project Background Section.

The following equation calculates the milliseconds for each "tick" of the PIC Timer1:

each PIC Timer1 tick (milliseconds) = 4 * prescaler / Tosc * 1000 where:

    • 4 is the MIPS for the PIC
    • Prescaler = allowable values 1,2,4,8
    • Tosc = PIC oscillator in Hz (24Mhz = 24000000)
    • 1000 = 1000ms/s (converts the calc to give clock tick in millisecs)

PIC microcontroller timers generate an interrupt on overflow, so the calculated number of clock ticks (equation above) need to be subtracted from the timer overflow value (65535 for 16-bit Timer1) to give the “starting point” for the PIC timer counting (which is the parameter used in the set_timer1() CSS compiler function).

Code Snippet 1:

void servoPulse(void) {
   if (input_state(OP_PIN)) { //high .: set for low part of pulse
   } else { //low .: set for high part of pulse

The values of "pulseLow" and "pulseHigh" in code snippet 1 are calculated by the following function.

Code Snippet 2:

void calcPWMparameters() {
 * Overview:   calculates set_timer1 values for PWM high portion (duty cycle), and
 *             low portion (the PWM period minus the duty cycle)
 * Dependency: assumes timer1 is being used (16 bit) with prescaler value = 2, 24Mhz system clock
 *             inputDuty is 8-bit integer 0-254, but represents 0 to 2.54 ms for duty cycle  
 * Notes:      1. because doesn't check/change values before existing PWM cycle has finished
 *                could get some funny jitter or similar on the servomotor
   float timerTickTime;
   float interruptPeriod;
   timerTickTime = (float)(4 * 2)/(24 * 1000000) * 1000; //gives ms/Timer1 tick where 4=PIC MIPS, 2 = prescaler, 24= PIC clock Mhz, 1000=ms/s conversion
   interruptPeriod = (float)inputDuty/100; //convert the integer 8bit representation into the desired milliseconds 0-2.54
   pulseHigh = 65535 - (interruptPeriod/timerTickTime);
   interruptPeriod = 20 - interruptPeriod; //20ms is the fixed length of the PWM period required by the SG90
   pulseLow = 65535 - (interruptPeriod/timerTickTime);
   interruptPeriod = (float)inputDuty/100; //JUST FOR PRINTF

Note: Image loading can be slow depending on server load.

Schematic 1: Basic SG90 Connection

  • SG90 SchematicSG90 Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    Schematic 1: Basic SG90 Connection

Schematic 2: SG90 with LDR sensors

  • SG90 SchematicSG90 Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    Schematic 2: SG90 with LDR sensors

This project did not require a PCB.

The construction was done using prototyping board. See the photographs and schematic diagram sections.

Qty Schematic Part-Reference Value Notes
1R110K1/4W, 10% 
1R83301/4W, 10% 
2LDR1,LDR2Light Dependant Resistor10K 
Integrated Circuits
1U1PIC18F248PIC microcontroller  datasheet
1U27805Linear Voltage Regulator  datasheet
1U3TL431Programmable Voltage Reg. Diode datasheet
1U4MAX232ERS232 Driver/Receiver datasheet
1J1CONN-H55-pin connector for ICSP
1X124MHzCrystal Oscillator
1Z1SG90Servomotor datasheet
Description Downloads
SG90 - Bill of Materials Text File Download

Unlike a straight DC motor, a servomotor cannot be tested just by applying a suitable voltage. The correct pulse width and frequency PWM signal is necessary. So the first step in testing the SG-90 is generating this PWM signal, which in this case is by using the PIC18F248 via an interrupt routine on Timer1 (see the Circuit Details Section).

The PIC18F248 PWM signal was tested with an oscilloscope to check that the desired pulse width and frequency were indeed being produced, and also that the PWM signal was stable. Any small change/fluctuations in the PWM signal will result in "jitter" of the servomotor. For example in this case of using a microcontroller, possible variable differences due to firmware code execution/interrupt routine operation (which could be a problem in a more complex application/firmware).

Having obtained the necessary PWM signal the SG-90 was energised to check the range of motion possible and the pulse width (i.e. duty cycle) necessary to produce various angular positions. The datasheet states that ~1ms pulse width for -90o, 1.5ms pulse width for "zero" or neutral position and ~2ms pulse width for +90o.

For the particular SG-90 being tested (I only had a single SG-90 so no information about variability) I found a minimum pulse width of 0.50ms caused the SG-90 to move to the maximum negative position (shorter duration pulse widths than 0.50ms caused the SG-90 to rotate to the end-stop). Conversely, the maximum pulse width was found to be 2.55ms which caused the SG-90 to move to the maximum positive position. The total range of angular motion was approximately 210o.

Using 1.50ms as the "zero" position, for the particular SG-90 being used, a 0.65ms pulse width for -90o and a 2.48ms pulse width for +90o provided a reproducible 180o range of motion. These results only loosely approximate those given in the datasheet (although the datasheet is very "rough" and likely only approximate in itself).

The Video Section provides visual results of the SG-90 in operation under various scenario's. From this testing a number of observations can be made as follows.

Rotational Speed

Using the video captured at 30fps the SG-90 was able to move an angular distance of 60o in ~0.1 second, which matches the datasheet.

Positional Stability

The SG-90 when at a particular angular position is very steady with no apparent jitter noticeable. This is factor of both the PIC18F248 producing a stable PWM signal and the SG-90 internal control circuitry being also stable.

Rotational Position

As discussed above, it was found for the particular SG-90 under test that a 0.65ms pulse width for -90o and a 2.48ms pulse width for +90o provided a reproducible 180o range of movement. Therefore, the following calculation provides the necessary pulse width (PW) in order to produce a desired rotational position (RP):

RP - 0/180 - 0
PW - 65/248 - 65


  • RP = input desired rotation position (degrees)
  • PW = necessary pulse width to produce RP
  • 65 = pulse width (scaled integer = 0.65ms) for 0o (i.e. -90o)
  • 248 = pulse width (scaled integer = 2.48ms) for 180o (i.e. +90o)


PW = ((
) * (248 - 65)) + 65

Video 2 shows the SG-90 rotating from a set -90o or "bottom" position (which is the "0" in the above equation) to increasing higher values (the "top" position is +90o or "180" in the above equation). The rotation position (i.e. the necessary pulse width) is calculated by the PIC18F248 using the above equation. A number of observations:

    • There is discrepancy between the actual rotational position of the SG-90 compared to the desired rotation position set by the calculated pulse width.
    • This discrepancy is greater when moving closer to what is defined as the "neutral" position "0" on the scale in the video's of the SG-90 operating.
    • There is a difference (i.e. possible hysteresis) if moving from +90o compared to -90o (compare video 2 and video 3)
    • The SG-90 returns very precisely to set positions (e.g. the -90o or "bottom" position in video 1)

The PIC18F248 firmware was extended to enable user input from PC/keyboard via RS232 for pulse width in steps of 0.01ms. Then the pulse widths necessary to achieve 10o angular steps from -90o to +90o were observed/recorded. These results were then recorded in the firmware as a lookup table. Video 4 shows the results of the SG-90 rotating to angular positions as a result of using this lookup table of pulse widths.

The difference between the lookup table values of observed necessary pulse widths and the calculated pulse width from the above equation is only in the order of a few tenth's of a millisecond. This hints that the SG-90 is capable of relative good angular resolution.

Video 5 shows the results of the SG-90 rotating to a particular angular position and then the pulse width is increased in steps of 0.01 milliseconds. The SG-90 can produce angular resolution of one degree.

The conclusion of these results is that the SG-90 has good resolution and reproducibility, but the precision in terms of angular position calculated for a particular pulse width is poor. If precise angular positions are required then potentially the "lookup table" approach is better (and possibly in the microcontroller realm more appropriate in terms of ROM/RAM and avoiding floating point calculations etc).

Motor Torque

The torque of the SG-90 is given in the datasheet as 1.8 kg/cm. This was tested by attaching a lever to the SG-90 horne (see photographs 7 and 8) to enable lifting a weight. Used distances of 2cm and 4cm from the SG-90 rotational axis from which weights were suspended. The SG-90 started with a pulse width of 1.55ms (weight on the ground, no applied force) and the pulse width was changed to effect a 10o rotation of the servomotor, which lifted the weight ~5mm of the surface. The necessary pulse width change and motor amps were recorded for various weights. The results are given in the following Graph 1.

The maximum applied force was 0.82 kg/cm (410gm at 2cm from the rotational axis) approximately half of the datasheet value. The SG-90 although "rated" as capable of 1.8 kg/cm only has plastic gears and when viewed very small gear tooth size (the whole component is only 9gms). Therefore, I was careful about avoiding "destructive" torque testing as I only had a single item on hand. Also, I noted that when using 4cm from the rotational axis for suspending weight in the torque test, I was unable to get the SG-90 to lift more than 160gm.

Graph 1: SG90 Torque Testing

SG90 torque test

As a general precauation double check polarity of power connections etc before powering up the IC. The SG-90 has a power supply requirement of DC ~5V (some datasheets state a maximum of 6V).

Mounting the SG-90 requires a suitable plate/surface through which a hole can be drilled to enable the output shaft to protrude and screws can be used to fasten the body of the SG-90 (see the diagram in the datasheet). For the purposes of testing the SG-90, stout cardboard was all that was required (see the pictures and video section).

The SG-90 when purchased came with 3 horns (small plastic "arms" which can be screwed into the output shaft) upon which any desired lever/cable/platform etc can be mounted to the SG-90, and thus rotation and or linear motion be imparted to the desired external component.

To enable the LDR's to track the brightest incident light source, they were mounted so that a small vertical partition "shaded" the LDR's in such a manner that an incident light beam cannot fall directly upon both LDR's simultaneously unless the LDR's are both perpendicular to the light beam (see pictures and video section).

Note: Video loading can be slow depending on server load.

The video's below show demonstrations of the SG90 servomotor in operation and during testing. The demonstration code is discussed in the "Background Section" above.

Video 1: SG90 mounting and circuit connections - showing operational

Video 2: Stepping from -90o successively greater 10o increments - PIC 18F248 calculating pulse widths

Video 3: Stepping from +90o successively greater 10o increments - PIC 18F248 calculating pulse widths

Video 4: Stepping from -90o successively greater 10o increments - using lookup table

Video 5: Demonstrating resolution (0.01ms increments in PWM pulse width)- PIC 18F248 calculating pulse widths

Video 6: Light sensing with LDR's controlling servomotor position (light source tracking)


No comments yet.

Add Comment/Question

Only Logged-In Members can add comments

"If we could sell our experiences for what they cost us, we'd all be millionaires".

Please donate any amount to help with hosting this web site.

If you subscribe (only $2/annum) you can view the site without advertisements and get emails abouts updates etc.



Only logged-in users with correct Membership Level can download.

Membership starts at only $2, so join now!