Serial Manipulator Control

Kevin Walchko

created 17 Nov 2017


Ok, so we have our forward/inverse kinematics defined. We now need to send commands to the robot arm to make it move. The lab will cover this, but this is just a little more information on: servos, angles to PWM widths, and coordinate frame alignments.

Objectives

  • understand how to convert desired joint angles into servo commands
  • understand how to compensate for real world mis-alignments
  • understand the differences between mathematical models and the real world
  • understand how to get your laptop to communicate with the robot arm

References

Setup


In [2]:
%matplotlib inline

from __future__ import division
from __future__ import print_function
import numpy as np
from matplotlib import pyplot as plt

Servos

The first thing you need to understand are the RC servos we are using are made by the millions at the lowest price point possible. Therefore, there are little differences between every servo and there is no standard input/output relationship between servos. Typically you need to calibrate your servos and determine the max/min PWM pulse needed to move your servo between 0 degrees and 180 degrees. Note, some servos turn more than 180 degrees and some turn less ... it just depends.

Parts

You should already be familar with a servo from ECE382. However, a servo allows you to command a motor to turn to an angle based off internal feedback from a potentiometer. This is nice, because it does not require you to develop a control system with a feedback loop.

But how does it work?

  1. The servo takes in a control signal and compares that signal to the position sensor (the potentiometer in this case) which then calculates the error between the two.
    1. If the signal and the position sensor have the same value, then the error is 0.
    2. If they are different, then there is error in the system.
  2. The error then gets multiplied by a gain (the amp in this case) to produce a voltage. This type of control system is referred to as a Proportional Control System
  3. That voltage then goes to the motor and drives the motor
    1. If the error is zero, then the motor voltage is zero and the motor stops
    2. If there is error, then the motor will turn in proportion to the amount of error

Again, these are not really standardized and every manufacturer does things a little different, but ball park PWM values are:

Commanding

For our robot arm, we do not need to directly talk to the servo. Instead we need to send commands to a servo driver board, which will drive the servo to the correct angle and provide power/ground. Now, our software we have developed in the homeworks will generate a joint angle (in degrees or radians), but we need to turn that into a PWM signal ... how?

Our servo driver board has a serial interface and expects a command in simple ascii text with the following format: #0P500 where

  • # is the message start character
  • 0 is refering to servo number 0, but can be 0-5
  • P800 is the command to position the servo at location 800, which could be between 800 and 2300.

Now the standard PWM counts for our servo driver board is:

Angle PWM Gripper PWM
0 800 Open 800
180 2300 Closed 2300

So if I wanted to position servo 3 at 90 degrees, I would want to send #3P1550 (1550 is half way between 800 and 2300) or I wanted to command the gripper to close #4P2300.

NOTE: For the lab you will need to develop a function (angle2pwm(angle) => PWM) which will take in an angle (in degrees or radians) and return the PWM width. Also, when you develop this function, you need to be able to adjust this range. The first part of the lab is calibration, where you will double check what PWM widths work best for your servos.

Reference Frame Corrections

Now we developed our forward/inverse kinematics using Craig's process, based on DH, but that assumes a certian orientation for how we measure angles. DH defines a rotation angle (how we want our servos to move) and the angle between $X_{i-1}$ and $X_{i}$. You need to be aware and compensate for when the real world servo orientation is different than our mathematical DH process.

Shown below are the angles for a servo on the left and the DH reference frame on the right. Notice they don't agree on the location of 0 degrees.

Here the problem is, your code (according to DH) tells you to move the servo to 0 degrees. Looking at the picture on the right, that means you want to be aligned with the x-axis (according to DH). However, sending a PWM signal to the servo for 0 degrees will rotate the servo so it is aligned with the y-axis (according to DH). You need to insert a conversion factor before you send the command to the servo.

So something like this:

# I want servo0 to go to 0 degrees in DH
offset0 = pi/2  # the frames are 90 deg off

pwm = angle2PWM(angle0 + offset0)  # the servo will now align to your DH axes

When you command the serovo to 0 degrees, it will go where you want. In your lab, you will have to determine good values for your servo's PWM values, you also need to understand where 0 and 180 degrees are so you can make corrections if needed.

Serial Communications

We will talk to the robot arm's servo controller using a Universal Asynchronous Receiver-Transmitter (UART) serial interface. These are very common and the microcontroller in the servo controller has one built in (so does the MSP430). Here we are using a USB-to-serial converter for our laptop.

The older model arms use the above, while the newer arms have the USB-to-serial built right on the board so all you need is a USB cable. The lab has the setup instructions so I won't repeat them here, but to write serial communications code in python, all you need to do is:

import pyserial

# let's create a serial port object
# the port (COM5) will be different on your laptop
# we set the datarate to 115200 for the arm, other applications could be different
ser = pyserial.Serial('COM5', 115200)

ser.write('hello')  # send some data, a string saying hello

# we won't need these for the lab, but I want to show you they exist
ans = ser.read()      # read in 1 byte
ans = ser.read(100)   # read in 100 bytes

ser.timeout = 1       # set timeout (how long to wait for data) in seconds
                      # readline() needs this set to work
ans = ser.readline()  # read in data that ends in \n or it will return when it times out

ser.close()  # all done, close the port

For the lab, all you need to be able to do is open, write, and close the serial port. See the pyserial documentation if you want to do more for another class.

You Now Have All the Tools You Need

When we get to the lab, you and your team are on your own. I have given you:

  • Forward kinematics
  • Inverse kinematics
  • Python code examples
  • Explained how the robot arm works

Good Luck!

Exercises

  • This lesson really is just a prep for the lab, make sure you combine your homeworks together into a program and account for the things we discussed today.