Modules

Hobby Servomotors


UObjects for servomotor drivers

This section is directed for those who wants to make their own servo driver for a custom robot, with URBI as software plattaform and a microcontroller as hardware control.

In this case the Microchip(R) PIC microcontroller is implemented, but it could be easily migrated to another plattaform, with the help of diagrams and algorythms included.

I hope this section could be useful for students, hobbyists or even researchers.

Alfredo Canto


Hobby servomotor "Hello world"

DESCRIPTION

This UObject provides an interface between a hobby servomotor and Urbi (on Windows). The tested servo was the Hitec model HS-85MG, however any similar servo can be used. In addition, the firmware of the driver is provided, in this case the microcontroller PIC18F2550.

REQUIREMENTS

- Software:

  • Urbi SDK 2.3 for Windows
  • Visual C++ 2008 (optional)
  • Pic C Compiler PCW 4.023 (optional)

- Hardware:

  • PIC18F2550 (or equivalent)
  • Hobby servomotor, pulse width: 0.65ms to 2.25ms @ 50Hz


FILES

- Common files:

  • UServo.cpp: The source code for the UObject module
  • UServo.dll: The module to be launched with Urbi
  • driver_serial.cpp .h: The virtual COM port handle class

- Customizable:

  • servo_driver.c .h .hex: The source code for the microcontroller
  • diagram.jpeg: Electronic diagram of the driver
  • servo_example.u: Example of use


HOW TO USE

- Hot plug and play.

Program the microcontroller with the hex file and connect the pasive components as showed in diagram.jpeg. Copy the dll and servo_example to the urbi path (...\Gostai Engine Runtime\bin) and lauch a new Urbi server with the module (urbi-launch -s UServo.dll). Finally load the example: load("servo_example.u");

- Urbi commands.
var servo = UServo.new;

servo.Attach(10); // Open the virtual COM number port
servo.Dettach;    // Close the virtual COM port
servo.Ini;        // Go to the initial position
servo.Go(45);     // Go to the specified position (degrees)
servo.Move(0);    // Move with the CW(0) or CCW(1) direction
servo.Hold;       // Stop the servo and hold position

servo.Get_speed(1);   // Get the approach(0), low(1) or high(2)
                      // speed parameter
servo.Set_speed(1,30);// Set the speed parameter
                      // speed = x*2.5 (°/s): 30*2.5 = 75°/s
servo.speed = 0;      // Set the speed mode to low(0) or high(1)
                      // This speed is just for Ini, Go, and Move

servo.pos;        // Get the current servo position* (degrees)
servo.pos = 90;   // Set the servo position

// * there is no "real feedback", the function returns the speed
// proportional to the current pulse width of the control signal

- Considerations

  • Once the microcontroller has been installed, look for the COM port number in the Device manager.
  • Ini and Go functions wait until the servo reaches the specifed position.
  • Move function doesn't wait for a response, the servo keeps moving without any other instruction and can be stopped with Hold.
  • The movement of the servo is limitated by the driver, so it can't go below the lower limit neither above the upper limit.
  • Get_speed waits for the parameter, but Set_speed doesn't wait any confirmation.
  • The approach speed is used with a threshold, when the current position is close to the desired position (for Ini,Go,Move).
  • The variable pos is used to set and get the current position When the value is set there's no wait for a response, and could be used easily with an Urbi trajectory generator.
  • Dettach close the port, but doesn't disable the other functions.


CUSTOMIZE

The UServo instance can be implemented with any other microcontroller. The new driver must handle the same communication protocol through the CDC specification (virtual COM port with an USB port), also the operational algorithm should be equivalent.

- Protocol

When an UServo instance is created the Attach function becomes available. This function open the virtual COM port and sends a single byte to the driver, an ID byte. Once the driver gets this byte it answers with an ID byte too, then the comunication starts.

Every time a command is sent, an ID byte indicates the beggining of the package, and once the driver responds, other three bytes are sent: command byte, data byte, and the ascii carriage return (CR=13). In the case of the Ini, Go, Get_speed functions and the access to the pos variable the driver responds with the corresponding data.

The command byte consist in a command ID of four bytes (the most significant nibble) and the other four corresponds to the parameters of the instruction. The following table resumes the current commands that the UServo handles:

Command/ParameterDataReturn
INIT
0x 00 - low speedNAYES
 1 - high speed  
GO
0x 10 - low speed0 - MAX_ANGLE*YES
 1 - high speed  
MOVE
0x 20 - low CWNANO
 1 - high CW  
 2 - low CCW  
 3 - high CCW  
POS
0x 3X0 - MAX_ANGLE*NO
FEED
0x 4XNAYES
SET
0x 50 - approach speed1 - MAX_SPEED*NO
 1 - low speed  
 2 - high speed  
GET
0x 60 - approach speedNAYES
 1 - low speed  
 2 - high speed  
HOLD
0x 7XNANO


* The value of the parameters are associated with the servo and the driver algorythm. In this case the angle can take a value from 0 to 160°, and the speed a relative value from 1 to 170, corresponding with 2.5 to 425 °/s.

- Driver

The algorithm of the driver is simple: in an infinite loop waits for a command, when it detects the ID byte respond with another ID byte and wait for the package (3 bytes), saving it in a buffer. Meanwhile two timers in the background count the specific time to set and clear the control signal through the corresponding interrupts.

One timer interrupts the main process to calculate the width of the next cycle, depending on the last received command. Then adjusts the time for the next interrupts and set the control signal.

The second timer is adjusted in the interrupt of the first one. Its function is to clear the control signal on the time proportional to the position calculated.

- Servomotor

Before connect a different servo with the driver, check the limits for the width of the control signal pulse. If the lower limit of the servo is above the lower limit of the driver, the servo could get damaged. The same with the upper limit.

DOWNLOAD

UServo.zip
diagram.jpg


Servo driver x8

DESCRIPTION

This UObject is an improved version of the single servomotor driver on Urbi and a Microchip Microcontroller. In this instance the driver is capable of handling up to 8 servos, each one of them with a different operational controlled speed, minimum pulse width, threshold, and position.

FILES

- Common files:

  • UServo2.cpp: The source code for the UObject module
  • UServo2.dll: The library to be launched with URBI
  • driver_serial.cpp .h: The virtual COM port handle class

- Customizable:

  • servo_driver3.c .h : The source code for the microcontroller
  • algorythm.pdf: Flowchart of the driver


HOW TO USE

- Urbi commands.
var servo = UServo.new;

servo.Attach(port);   // Open the virtual COM number "port"
servo.Dettach;        // Close the virtual COM port

servo.Move(id,angle); // Move servo "id" to the position "angle"
servo.Feed(id);       // Get the servo "id" current position*
servo.Hold(id);       // Stop the servo "id" and hold position

servo.Set_speed(id,spd);   // Set the servo "id" speed
servo.Set_base(id,width);  // Set the servo "id" minimum PW
servo.Set_thres(id,angle); // Set the servo "id" threshold angle

servo.pos0;        // Get the current servo 0 position* (degrees)
.
.
.
servo.pos7;

servo.pos0 = 90;   // Set the servo 0 position (same as Move(0,90))
.
.
.
servo.pos7 = 90;

// * there is no "real feedback", the function returns the speed
// proportional to the current pulse width of the control signal


"id" takes a value between 0 and 7, corresponding to the servos; "spd" is a positive integer for the speed (where a unit corresponds to 1°/s, up to 9 bits); "width" is the minimum pulse width for each servo control signal (where a unit corresponds to 10us, up to 8 bits); "angle" is the desired position in degrees or the threshold angle range for decelaration (where a unit corresponds to 1° or 10us, up to 8 bits).

http://www.youtube.com/watch?v=xLA_mDGS2js

- Considerations

  • With the Move command the servo moves with the speed set with Set_speed. When it's close to the desired position it moves with a lower speed (fixed speed in the driver).
  • Be careful when using Move and Set_base: the sum of the desired position and the base width can't be greater than 250 (2.5ms), otherwise the pulse will overlap with the next channel.
  • In this commands it is assumed that 10us correspond to 1°.


DOWNLOAD

UServo2.zip

Options: