Main Site Documentation

Servo16 Communication


#1

I would like to know if it is possible to communicate with the Servo16 Device at 38k4 instead of 2400. While I already know how to send the command:

byte[] baudCommand = new byte[8] { (byte)’!’, (byte)‘S’, (byte)‘C’, (byte)‘S’, (byte)‘B’, (byte)‘R’,0, 0x0D }; //!SCSBR

further communication from that point doesn’t not seem possible.

Does anyone have any ideas?


#2

Sending the command will change the baud on the servo board but did you change the baud on fez?


#3

So I changed the baud rate to:
static UInt32 BAUD_RATE = 38400;

and recalculated:

BIT_TIME_US = 1 * 1000 * 1000 / BAUD_RATE;
BYTE_TIME_MS = (int)Math.Ceiling((double)BIT_TIME_US * MAX_TIMINGS_BUFFER_SIZE / 1000);

however no joy.

(slight correction to the command to set the baud rate: “…(byte)‘R’,1, 0x0D…” )


#4

Our sample driver uses OutputCompare so you can use any pin to connect the servo board. This works well at 2400 or even 9600 but I do not think it would work well at higher baud rates. You will need to use one of the serial ports


#5

No higher than 9600 baud :frowning:

It seems that output compare is turning the bit on and off in step with some sort of clock that can’t support 38,400 baud.

So then how do I wire into one of the “Serial” ports on the FEZ_Domino?

(addendum)

To clarify, I know that there is a com port on pins D1 and D0 however I don’t know how to connect them to the Servo16.


#6

Look at the domino and find the pin that says TX (D0 or D1). Connect this pin to your servo board. Leave the RX pin unconnected. When that is done, look in the book on how serial ports work and change the code to send the data using serial port instead


#7

So I need to connect Di1* (COM1 OUT), which should be the Tx, to the Servo16’s serial port (any one will do?) If so then I understand that part.

So then how do I get data back from the Servo16 to determine the position of the servos? Which Servo16 connector do I connect to Di0 (COM1 IN, the Rx).

http://www.inexglobal.com/downloads/zx-servo16_e.pdf

If I figure all this out I’ll have to write a tutorial and a driver on how to connect Servo16 to Fez via the COM ports.


#8

You are right, the TX is OUT and RX is IN. You can change the code to you can move the servo using serial port object instead of OutputCompare.

Now, the board doesn’t have JST connector for reading. I do not know why inex didn’t add one! If you want to read then you need to use the other RJ connector, the one that is similar to phone jacks. On that side you would have TX and RX.

The easiest way to connect this is by using the RS232 shield and then use the RJ cable we have. If you know soldering/wiring then you do not need any of this.

http://www.tinyclr.com/images/products/TCLR-RP0122_large.jpg
http://www.tinyclr.com/images/products/TCLR-RP0106_large.jpg


#9

That RS232 Shield is gonna take a while to get here. In the mean time do you know how that cable of yours is wired? If I had to solder one together to connect my component shield to the servo16 how would I go about doing that? I know this question is a bit vague… sorry but I don’t know much about electronics :frowning:


#10

Then it is better to wait.

You can now control the service using a real serial port. When you receive the rest of what you need then you can work on reading the position of the servos.

Reading the position of the servos is not an important feature. It may not be worth your efforts. You can have a local variables that store the servo positions instead of reading position serially.


#11

Hehe, sure I’ll wait for the part.

But the reading of the position is actually important to me. My project (a delta robot) requires that I send commands to the servos within a tight time frame. One servo might be commanded to go to an angle at a certain speed while another is racing to a different point at a faster speed, while still another is not told to start up until the first servo is half way to its destination :slight_smile:

While I wait for the part I’ll keep busy with developing the driver for the timed commands. I’ll try it and let you know you it went.


#12

O.K. got it working. Yahoo!
In my elation I realized that there is another problem in that the Servos don’t lock in position after the command is sent. I suppose I’ll have to contact that manufacturer about that one.

Here is the code that I used to achieve this milestone.


using System;
using System.IO.Ports;
using System.Threading;
namespace Delta {
    public class Program {
        //template byte array for the command to set the servo motions
        static byte[] _command = new byte[8] { (byte)'!', (byte)'S', (byte)'C', 0, 0, 0, 0, 0x0D };
        //template byte array 
        static byte[] _setSpeed = new byte[8] { (byte)'!', (byte)'S', (byte)'C', (byte)'S', (byte)'B', (byte)'R', 1, 0x0D }; //!SCSBR
        static SerialPort _servo16 = new SerialPort("COM1", 2400, Parity.None, 8, StopBits.One);
        public static void Main() {
            
            _servo16.Open();

            //This will change the baud rate to 38400
            //_servo16.Write(_setSpeed, 0, 8);
            //_servo16.Close();
            //_servo16.Dispose();
            //You need to reopen the port at the new speed since there doesn't
            //seem to be a way to change the speed of an active port?
            //_servo16 = new SerialPort("COM1", 38400, Parity.None, 8, StopBits.One);
            //_servo16.Open();

            Random _randomPosition = new Random(0);
            Random _randomMotion = new Random(0);
            Random _randomSleep = new Random(200);
            
            //at random intervals, randomly position 3 servos at random ramping speeds.
            while (true) {
                SetServoPosition(0, (byte)_randomMotion.Next(63), (byte)_randomPosition.Next(180));
                SetServoPosition(1, (byte)_randomMotion.Next(63), (byte)_randomPosition.Next(180));
                SetServoPosition(2, (byte)_randomMotion.Next(63), (byte)_randomPosition.Next(180));
                Thread.Sleep((byte)_randomSleep.Next(1000));
            }
        }

        /// 
        /// Sends a message to the Servo 16 to set the position of the servo. Obtained from the original
        /// Servo16 Driver by GHI Electronics, LLC
        /// 
        /// Servo channel number between 0 and 15
        /// Ramping speed between 0 and 63
        /// Desired angle of the servo between 0 and 180
        public static void SetServoPosition(byte channel, byte ramping, byte angle) {
            if (channel > 15 || ramping > 63 || angle > 180) {
                throw new ArgumentOutOfRangeException();
            }
            // convert to 250 - 1250
            int position = 100 * angle / 18 + 250;
            _command[3] = channel;
            _command[4] = ramping;
            _command[5] = (byte)position;
            _command[6] = (byte)(position >> 8);
            _servo16.Write(_command, 0, 8);
            //the servo16 responds after 1.5 ms with a confirmation of the action
            //since we can't currently read the response we'll just wait twice as long
            Thread.Sleep(3);
        }
    }
}

#13

Maybe ti is not meant to stay in position by design. You will have to continuously keep sending the position to keep the servo active…I am just guessing :expressionless:


#14

I truly hope not. The product was advertised as set-it-and-forget-it. If that’s the way It’s supposed to work then I’m sunk :frowning:


#15

It shouldn’t be a big deal. You have FEZ with threading :wink: Creating a thread to send the servo position shouldn’t be a big deal. There also maybe commands to set it and forget it like you said. I am just assuming things.


#16

Hum… So setup a thread to send the commands to the servo16 as fast as possible constantly. Then update a thread safe list with the values for the servos while that thread is running. Sounds dubious but for now I’ll try it.


#17

So I contacted the Manufacturer (in Taiwan) and got an initial response, however subsequent responses have been slow in comming. If it ever arrives I’ll put the result in another forum post.


#18

Should not be hard to keep the servos positioned. Just create a thread like Gus said. You can start the thread and leave it in an infinite loop.

I have 18 servos of a cheap make (5 euro/servo) and they work very very well. For that price you do not even need to stumble across some sort of chinese websites… :smiley:


#19

While the infinite loop is a good idea, I don’t think the Usbzi is powerful enough to do that, the Inverse Kinematics and the line calculations required to control the robot :frowning:

So given that the Servo16 doesn’t lock, provide a Rx pin; I’ve decided that I’m not going to use it. I’m pinning my hopes on the PWM pins of the fez (i.e. even more workload on the cpu)

Worse, I found out that hobby servos don’t provide feedback on the actual position of the arm! So I’ve had to modify them to add a line from the center of the POT of the servo to the Fez 10bit ADC pins so that I can confirm the position of the servo. It sucks to be me.


#20

Yes servos do not give feedback. You can use a more fancy servos like this one (link removed)