One of the essential component for automation or robotics is servo. R/C modelers uses servos directly connected to R/C receivers. Embedded developers can interface servos with the micro-controller. Many micro-controllers like Picaxe, Basic ATOM or Ardunio has already methods to control servos. Let’s see how easy it is to control servo from .NET Micro Framework.

How does servo work?

Servomechanism or servomotor is DC motor with gear and control electronics. Advantage of servo is, that can be precisely set to desired position. Limitation of servo is, that rotation angle is only 90 degrees - practically it is 180 degrees. Adjusting the precise position is done by the control electronics embedded in servo.

Electronics in servo accepts PWM (pulse width modulation) signals and translates them into appropriate steering angle. Even if the PWM may sounds scary, it’s nothing else than logic 1 set to servo control input for certain amount of time. Recommended pulse width is from 1 ms to 2 ms for rotation from -45 to +45 degrees. It means that center position can be set by pulse of width 1,5 ms. Most of the servos supports rotation from -90 to +90 degrees so the appropriate pulse width is from 0,5 ms to 2,5 ms. However, these values are not supported by manufacturers and it’s important to be very careful when setting these limit values. Usually it’s good to start with 1 ms pulse width and then slowly decrees the pulse width until servo hit’s the inner physical sentinel. Pushing servomechanism against the sentinel for a long time may cause damage to servo. Figure 1. shows the relation between pulse width and steering angle. Note that this values may not exactly correspond for all servos from all manufactures, but the deviations will be small. Pulses are send in approximately 20 ms intervals.

Servo pulse width diagram 500x180 Figure 1: Servo pulse width diagram

Servos and Micro Framework

From previous paragraph is obvious that only the OutputPort is necessary to control servos from .NET Micro Framework. Whole process will looks like this:

  1. Write true on OutputPort
  2. Wait certain time to keep pulse width
  3. Write false on OutputPort
  4. Wait and repeat from step 1

The only problem is with point 2. and 4. How to wait? Standard Thread.Sleep() methods accepts values only in milliseconds, so values like 0,5 ms or 1,5 ms or 2,5 ms is impossible to pass to this method. So the first step is to write the Sleep method, that accepts values in microseconds and blocks the current thread for this amount of time. Following method DelayMicroSec takes delay in microseconds, counts appropriate number of time ticks (one tick is one hundred nanoseconds) and then waits in while loop until the “Stop Time” is reached.

/// <summary>
/// Blocks thread for given number of microseconds
/// </summary>
/// <param name="microSeconds">Delay in microseconds</param>
private void DelayMicroSec(int microSeconds)
{
    DateTime startTime = DateTime.Now;
    
    int stopTicks = microSeconds * 10;

    TimeSpan divTime = DateTime.Now - startTime;
    while (divTime.Ticks < stopTicks)
    { 
        divTime = DateTime.Now - startTime; 
    }
}

Once the the microseconds delay is solved, the MoveServo method is much easier. It sends sequence of pulses of given pulse width. The sequence is repeated 30 times, which is enough to move servo from -90 to +90 degrees. It would be much sophisticated to keep actual position of servo and change the sequence frequency accordingly to distance that will be traveled. To center servo call method with 1500 as an argument.

/// <summary>
/// Moves servo by given pulse width
/// </summary>
/// <param name="pulseWidth">pulsewidth for PWM</param>
private void MoveServo(int pulseWidth)
{
    // Maximum time for pulse is 25000 microsec.
    int pause = 25000 - pulseWidth;

    for (int i = 0; i < 30; i++)
    {
        servoPort.Write(true);
        DelayMicroSec(pulseWidth);
        servoPort.Write(false);

        DelayMicroSec(pause);
    }
}

Connecting the servo

There is nothing special about connecting servos to micro-controller. Every servo has three wires, colors may differs for different manufacturers but mostly this color-schema is used. Black wire is connected to ground. Remember that in case of different power supply for servos and for micro-controllers, the ground must be common. Red wire is power supply. Most standard size servos are powered from 4 to 6 Volts, but 7.2 Volts are proven to be acceptable, especially when more servos are powered. Speed and force of servo is derived from input power voltage. Yellow or White wire is for control logic. It’s connected to CPU or other device that will control the servo. In real applications it’s recommended to put resistor between servo and CPU as a sort of protection.

Servo connected to micro-controller 270x150 Figure 2: Servo connected to micro-controller

Demo application

Demo application that runs on video is pretty simple. Hitec HS311 servo is connected to 5V power supply on Tahoe board and yellow control wire is connected to GPIO pin 1. Pressing the left button on Tahoe rotates servo maximum left, right button gives maximum right and select button centers the servo. When connecting other servo than Hitec HS311, verify the limit pulseWidth values in OnButtonDown method. Start with pulseWidth values from 1000 to 2000 and then slowly expand the interval.

Download demo application: ServoControl.zip [28.8 Kb]