Links to stuff on this blog

Use the Site Index of Projects page link above for an easier way to find stuff on my blog that you might be looking for!

Friday, October 16, 2009

Naked Lady Mannequin Coat Rack (I call it Frankie)

If you are like me you probably have a few plastic female torsos laying around the house and quite possibly a coat or two looking for a place to reside. OK... I don't have more than one naked female mannequin torso's  - I only have one - because having one is 'normal' and having a bunch of them would be 'weird'. I picked this thing up from a sporting goods store in San Francisco that was going out of business and selling off all their stuff. I  have to say that I didn't buy it because that too would be weird - paying money for something like this - it was given to me - sorta. I was at the store after they had gone out of business and closed down with a bunch of other guys that were taking down all the store display racks. We were taking all these shelves and racks to the place that I worked because at the time we were setting up a retail store near Fisherman's Wharf - sorta.



  
Anyway my employer bought all the shelving from this store and we were all there taking the shelves and displays down as were other 'crews' of people getting other things that they had bought. Near the door were these two swimsuit mannequins and I asked the guy in charge if I could take one. He looked at me like I was weird and said get "it out of here!" So off I went with it back to my office... from there I had to take it home on the BART Train (public transportation) and I thought I would get some really strange looks and people laughing at me for carrying a naked female torso under my arm - but I was in San Francisco and that isn't weird - in fact few things are really weird in that city compared to what is an adjusted 'normal'

So after getting it home I had to figure out what to do with it. Putting clothes on it seemed to be the right thing to do but before I could do that I had to make it stand up by itself. Because it didn't have any legs I cut up some black PVC pipe and drilled some holes in the bottoms of the truncated leg stubs. The two pieces of pipe are a lot longer that they look in the picture because this thing is hollow. So I jammed the pipes up inside the body until the wouldn't go in any farther. I cut the pipe parts that were sticking out so they were the same length and glued on the U pipe joint. This essentially made the two pipes into one and gave me a place to glue in a short piece of pipe. Out in the backyard I had a couple of those old direct TV dishes that someone gave me and I laid it flat on the floor and attached the single PVC pipe to it. Check out the picture if this description isn't clear.

The top pipe sticking out of where the neck/head would be is actually part of the mannequin, it was designed to hang from that. These things were hanging by their skinny pipe necks from the ceiling in the store. I didn't mention that at first because it sounds weird. I figured if you have read to this point of the blog it wouldn't sound so weird. Am I right?
 


So to cover up the strange pipe sticking out the top I put my hat on it. I did consider building a transparent head bowl like thing with lights in it - and using that for a head - and I still may do that. I think it would look good if it had something that lit up when someone walked by or made noise... kinda like the lamp that I made. or maybe it could have a scrolling message but I'd have to think up something funny for it to say. For now it's just a coat rack and hat holder.
I bet that you want one !

Sunday, October 11, 2009

More on the home made robot... starting to walk

After a long weekend I finally got the Python code to work the way I wanted it to and I am able to more easily control the motors. Most of my time over the last several days has been spent figuring out how Python works and not really messing with the robot motion directly. Because of that I'm tired and don't have the time to get a really smooth walking motion today. What I currently have does work but it jerks along the floor and doesn't make the 'forward motion' that it should be doing based on how much the legs are actually moving. I do count this as some success because it should be easier from where I am at now to get it to at least walk.
 

 
What you can see from the video is that all 4 of the legs are moving in cyclical 'walking' motions but they are not coordinated enough to really get the robot to move forward. This is because at a few points in the cycle some of the legs are moving forward and others are not. So when it's trying to walk on the floor the legs that are not moving are being dragged along!!! Oh well like I mentioned I have spent all my energy getting the code to work and not on actually the motion.
 
The progress that I did make this weekend was I managed to figure out how to use the import statement in Python to bring in a chunk of code that defines some custom commands that I wrote. What that means is now I can write a script like this:
  
PS.ServoPos(6,2200)
PS.ServoPos(7,4300)
time.sleep(.2)
 
So what is going on in the above code is I can just directly address the particular motor I want and send it to a particular position. For example the first command PS.ServoPos(6,2200) is sending servo number 6 to position 2200 !!! WOW! I'm sure all you Python gurus out there are laughing at me but considering I'm not a programmer and I have only been using Python now for 12 days or so it's an accomplishment.
  
Here are the steps that I listed in my Last Post that I wanted to get done with updates to each:
  
1) figuring out a clean way to mount the Pololu board to the robot base with it's one mounting hole
    I mounted the board and made a strain relief for the cables (see picture below)
2) cable management to make sure the servo wires don't get all tangled up while it's running
    I can't say that they are under control but the cables now don't get tangled!!! (see picture below)
3) using the jog program to get the remaining leg hard stop values
    I got this done and wrote a little converter program to help (see source code below)
4) hours of coding and testing to make this thing walk!!!
    When I wrote hours of coding and testing I was underestimating the task... lets say DAYS of coding!
 

   
A picture of the Pololu board mounted to the Epson Printer Base that I cut up and turned into the robot base. The black plastic on top of the board with the wires coming out of it is a piece of 0.04" thick ABS plastic that I cut and screwed to the base. There is a second piece of ABS as well that is sandwiching the wires in there with some rubber bands to hold it together. It's not elegant but it works to keep the Futaba servo connectors from being pulled or worked off the Pololu board while the robot is running.
  
The next thing to do at this point is refine the walk cycle to get all the legs to move together so it can walk instead of dragging its feet along the floor. As soon as I get that done I'll post another video of it walking.
 
Below is the Python code that I wrote to help with the programming of the Pololu board. The Pololu requires position commands that range from 500 to 5500 to position the motors. When sending the position to the Pololu board you have to take a position like 3800 and convert it into 2 bytes of data with the Most Significant Bit of each of those two bytes set to 0, shifting bits around as needed.
 
So 3800 decimal  = 
00001110 11011000 binary 
which then has to be converted to 
00011101 01011000
which is equal to two bytes of
0x1D 0x58
 
Anyway doing that by hand is a pain so I wrote the program below to do it for me. This was handy when figuring out positions that I wanted to have defined in the function calls that I wrote.
  
#  Pololu Range Converter
#  Written By Otto Belden Oct 2009
#  http://ottobelden.blogspot.com/search/label/Robotics
#  This will take a input from the console and print out the
#  high and low byte that the Pololu needs to position the servo
#  with the MSB of each of the two bytes 0 as required by Pololu
#
import sys
# Set a default position
pos = 2500
while pos != 0:
    pos = int(raw_input("Give me a number or 0 to exit "))
    if pos == 0:
        print "Exiting..."
        break
    # get the data 1 byte (high byte)
    data1 = (pos-(pos&127))/128
    # get the data 2 byte (low byte)
    data2 = pos&127
    print " Position = ", pos, "High Byte = Ox%x"%data1,"Low Data = 0x%x"%data2

Wednesday, October 7, 2009

DIY - Homemade (free) Shop Dust Collector (Disperser)

It's getting a little dusty and dirty in here... well it was until I made my very own shop dust collector! With all the work that I do dust is a big problem especially when wood turning on my Homemade Lathe. Of course and sanding, cutting and drilling also generates a lot of dust. Aside from being unhealthy it is also a pain as dust gets everywhere. No matter what I do it ends up in the house, upstairs, in my nose and pretty much every other place that  you can imagine. UPDATE: I wrote a new post with more details HERE with a video have a look!
  
To deal with this I decided to build a dust collector system that uses a radial blower. I chose a radial blower for this because they tend to be better at building up (static) pressure compared to a fan type but also I happened to have a blower that I wasn't using for anything (free). The static pressure part is good because to really work as a dust collector I have to not only suck up the dust but blow it through a filter of some kind. Filters especially when they get dirty and clogged don't pass air too well and the back pressure builds up. A radial blower can keep the pressure up and keep the air flowing.
  
So step one was to get a suitable container to collect the dust. I decided a paint bucket was just about right because of it's convenient size but also I happened to have one laying around that I wasn't using (free). Here is a picture of the finished system.
 
Finished Homemade Dust Collector

Saturday, October 3, 2009

Robotic Leg Testing with Python, Pololu and some good luck...

A day or so ago I got my Pololu USB 16 RC Servo Controller board in the mail. This is a USB or serial controlled RC Servo controller that can handle up to 16 RC Servo motors simultaneously. The board takes serial data from either the standard mini USB connection or a RS-232 connector and turns it into the pulse train necessary to position the RC servos. The handy thing about this board (and other like it) is that the board takes care of the pulse generating and all you have to do is sent it a serial string of data to tell it which motor goes to what position - the board takes care of the pulses.
  
For my initial mechanism testing I built a little test box that had an oscillator and three 'one shot' pulse stretchers that I could control with potentiometers to get the desired pulse train. That was good enough to test the mechanism one part at a time but for the coordinated motion required for exciting robotic action I need something like the Pololu USB 16. Because my robot has 3 servos per leg and a total of 4 legs I need to be able to control 12 servos and the Pololu handles 16... so far so good with 4 to spare....

My initial impression of the Pololu USB 16 is that it's small and only has one mounting hole to mount the board. The small size is great but the single mounting hole will make it an interesting challenge to mount it to the robot base. The other thing that I noticed about it is the servo power connector wasn't soldered to the board itself when I got it. I decided to solder it to the backside of the board since on the component side it will cover up the silkscreen on the board and make it hard to connect the servos to the header. Not a big deal I guess. I didn't bother to figure out a way to mount it just yet, I thought I'd better test it first. So I just set it on the robot base and hooked it all up.
 
Sorry about the fuzzy picture but you get the idea.

 
 
Another nice thing about the Pololu is it comes with a driver that once installed lets the USB connection to the Pololu board look like a standard serial COM port on your computer. That way controlling the Pololu is done by sending serial data out the COM port (really the USB). This is handy because most computers, especially laptops these days don't have an actual serial COM port.

The first thing that I did to make sure that this was all working was write a simple Jog test program in Python. I'll post the code for this at the end of this blog post. The code is mostly mine with a bit of the data conversion stuff from an example on the Pololu website. I used this jogger program to incrementally move the servos to their mechanical stops. I had to do this because the travel on each servo is 180 degrees but my robot leg mechanism doesn't use all 180, mechanically the linkages wont go that far. Each time I moved the servo with the jogger program it prints out the actual servo position and once I was at the mechanical stops I wrote down that position for each servo. As long as I don't tell the servo to go past that position I won't 'crash' the robot mechanism into it's hard mechanical stops.

Once I had all the mechanical stop positions written down I wrote a simple 'exerciser' script that moves the servos through their ranges. This was not only to test the mechanism but also to help me figure out how Python programming works (I'm not a programmer). Also this allowed me to see how well the Pololu handles coordinated motion of multiple servos. I made a 28 second grainy and dark video of the leg running this script.
 


It looks like the Python code talking to the Pololu USB 16 board works pretty good at getting everything running at the same time. All three servo's ran as expected without crashing into anything and the motors run at the same time as opposed to stepping through each motion one at a time.

The next immediate steps in the robot development are going to be:
1) figuring out a clean way to mount the Pololu board to the robot base with it's one mounting hole
2) cable management to make sure the servo wires don't get all tangled up while it's running
3) using the jog program to get the remaining leg hard stop values
4) hours of coding and testing to make this thing walk!!!

Here is the Python code of the Jogger program that I wrote. I want to say again that I am not a programmer and I have only been writing Python code for 4 days now so it probably isn't the best example of how to do this - but it woks. If you are a Python Guru please let me know what I can do to improve my code especially if it will make the next programming task (walking robot) a bit simpler and easier for me. In other words HELP!!!!   ;-)

- Python Pololu USB 16 Servo Jogger Program - 

Python needs to have everything indented correctly with spaces to run and the copy/past from Python IDLE seems to have removed some of those. You may have to tinker a bit to get it to work and look right in the Python editor but all of the code below works on my Windows Laptop running Python with the pySerial module loaded. PySerial gives you the serial commands to write out the virtual COM port (really a USB connection) that the Pololu USB driver sets up when you plug in the Pololu board.
   
# Pololu Motor Range Finder or Keyboard Jogger
# Written By Otto Belden Oct 2009
# http://ottobelden.blogspot.com/search/label/Robotics
#
import serial
import sys
#
#set com 3 up for communications Pololu defaults to com 3
ser=serial.Serial(2)
ser.baudrate=9600
# set the speed of Servo at something slow and reasonable with
# a varaible serstr = Serial String to write to com port
#           Start     DevID   Command  Servo     Data1
serstr = chr(0x80)+chr(0x01)+chr(0x01)+chr(0x02)+chr(0x10)
ser.write(serstr)
# set a default position at a mid range position for the servo 2750
# which breaks down in Pololu speak to 0x15 0x3E Data 1 and Data 2
# a varaible pos = position
# then build a new Serial String using that position and send it out
pos = 2750
#           Start     DevID   Command   Servo     Data1      Data2
serstr = chr(0x80)+chr(0x01)+chr(0x04)+chr(0x02)+chr(0x15)+chr(0x3e)
# define function newposition() that will calculate the 2 byte positions
# from the current position and assign those bytes to Data1 and Data 2
# then write out a new string
def newposition():
    if pos <=700 or pos >= 5300:
        print "******WARNING SLOW DOWN******"
    # get the data 1 byte (high byte)
    data1 = (pos-(pos&127))/128
    # get the data 2 byte (low byte)
    data2 = pos&127
    #           Start     DevID   Command    Servo     Data1      Data2
    serstr = chr(0x80)+chr(0x01)+chr(0x04)+chr(0x02)+chr(data1)+chr(data2)
    ser.write(serstr)
# print out to the console the instructions and keys to use then get keypresses
print "The servo should be on right now and in the middle of it's travel"
print "Use the '1' and '2' keys to jog the motor Forward and Reverse 100 counts"
print "Use the '3' and '4' keys to jog the motor Forward and Reverse 50 Counts"
print "Use the '5' and '6' keys to jog the motor Forward and Reverse 10 Counts"
print "Use the '7' and '8' keys to jog the motor Forward and Reverse 5 Counts"
print "Hit the '0' key to quit\n"
Input = 1
while Input != 0:
    Input = raw_input()
    Input = int(Input)
    if Input == 0:
        print "Now exiting last position was ",pos
        ser.close() # close the com port befor exiting
        print "Com port is open =",ser.isOpen() # make sure the port is closed
        break
    if Input == 1:
        pos = pos - 100
        newposition()     
    if Input == 2:
        pos = pos + 100
        newposition()
    if Input == 3:
        pos = pos - 50
        newposition()     
    if Input == 4:
        pos = pos + 50
        newposition()
    if Input == 5:
        pos = pos - 10
        newposition()     
    if Input == 6:
        pos = pos + 10
        newposition()
    if Input == 7:
        pos = pos - 5
        newposition()     
    if Input == 8:
        pos = pos + 5
        newposition()
    print "New Position  = ",pos