Monday, August 17, 2015

An aside: USB Power Switch

 If your like me, you don't want to have to unplug the power from the wall or you Raspberry Pi every time your done, or dig to plug it back in. The solution? A simple switch, built right into you USB cable.
***WARNING: This is a power switch, it will not shut down your Raspberry Pi. That you will have to do manually on the Raspberry Pi. Failure to do so will damage your Raspberry Pi***
Now that that is out of the way...
Let us do this!
<!--more-->
 The first thing you will need is a USB cable. Don't bother with the super expensive 90' ones. This simple one from Walmart for powering a phone will do fine.

This one comes with a micro and mini usb end. We only need the one, and are going to  cut the cable anyway. So, take the one you want, set the rest aside.

After you have cut the one you want, DO NOT cut the rest of the wire yet. Just strip the ends of the red and black wires inside. This one doesn't have them, but a data cable would also have a green and white, plus some shielding. We don't have use for any of these, cut them back. After you have stripped the wires, twist them so there are no loose wire, the tin them(presolder). This will get us ready for the next step.

Next, slide some heat shrink tubing big enough for the cable all the way to the plug. Then put some smaller over the red wire. This is positive and will be soldered to the switch. Choose a switch. Any two pin will do. Connect the red wire to one of the pins. It doesn't matter which, but will decide how the switch lays along your cord. Solder it in place, slide the smaller tub up, and shrink it around the exposed end of the wire and as much of the pin as you can. Leave the ground(black) alone for now.

Now that you know better how long the male end is with the switch,  cut the male end to the length you desire. I made mine short as it will be going from a battery to the Pi, right next to each other.

 Then repeat what you did for the first pin on this side. Don't forget a piece of large tubing for the whole wire, and a smaller one for the positive where it connects to the switch.(As you can see above, I did) After you have both positives connected and your ground wires pretinned, add a heat shrink tube to one side, and splice them together. I like to add a little more solder, but some just use the pretin to connect them. Shrink the tube around the join. I then take a small piece of electrical tape and fold it over the to terminals(pins) on the back of the switch. This will protect them from shorting on anything that may be around. Make sure it sticks out, onto the cable on either side. Then take both of your two larger tubes, slide them as far under the switch as you can, with the ends of the tape inside. Then shrink them all down, giving you a nice clean back cover, with no exposed wires.

I have seen people use some epoxies to cover the back, giving it a hard stiff, protective cover. Your final product should take into account the environment it will be subjected to. Mine will be inside another case, with only the switch visible, so a soft back will do fine.

Thanks for reading, I hope you found this useful in some way.

Until next time, keep building.

Thursday, August 13, 2015

Freedom!

A pretty short one today. I finally got my battery, so I can now run the Pi remotely, under its own power. Which mostly means I just sit at my computer, running it over things. I still wouldn't call it a robot, more of an R/C Tank. But it is getting there. While I don't have any real building today, I do have a bit of code. So...

Let us do this!
<!--more-->
A R/C Tank isn't any good without control, right? So how do I do it.
This is how:
import RPi.GPIO as GPIO
import time
import pygame
import sys
import pygame.camera
from pygame.locals import *

#Pin definition for drive control
in1_pin = 5 #Right back
in2_pin = 6 #Right forward
in3_pin = 12 #Left back
in4_pin = 13 #Left forward
enableA_pin = 16 #Right side
enableB_pin = 26 #Left side

#Setup pins
GPIO.setmode(GPIO.BCM)
GPIO.setup(enableA_pin, GPIO.OUT)
GPIO.setup(enableB_pin, GPIO.OUT)
GPIO.setup(in1_pin, GPIO.OUT)
GPIO.setup(in2_pin, GPIO.OUT)
GPIO.setup(in3_pin, GPIO.OUT)
GPIO.setup(in4_pin, GPIO.OUT)

pwmA = GPIO.PWM(enableA_pin, 500) #Right side throttle
pwmB = GPIO.PWM(enableB_pin, 500) #Left side throttle
pwmA.start(0)
pwmB.start(0)


GPIO.output(in1_pin, False)
GPIO.output(in2_pin, False)
GPIO.output(in3_pin, False)
GPIO.output(in4_pin, False)

#drive commands
def forward():
    pwmA.ChangeDutyCycle(100)
    pwmB.ChangeDutyCycle(100)
    GPIO.output(in1_pin, False)
    GPIO.output(in2_pin, True)
    GPIO.output(in3_pin, False)
    GPIO.output(in4_pin, True)

def reverse():
    pwmA.ChangeDutyCycle(50)
    pwmB.ChangeDutyCycle(50)
    GPIO.output(in1_pin, True)
    GPIO.output(in2_pin, False)
    GPIO.output(in3_pin, True)
    GPIO.output(in4_pin, False)

def spinRight():
    pwmA.ChangeDutyCycle(100)
    pwmB.ChangeDutyCycle(100)
    GPIO.output(in1_pin, False)
    GPIO.output(in2_pin, True)
    GPIO.output(in3_pin, True)
    GPIO.output(in4_pin, False)

def turnRightForward():
    pwmA.ChangeDutyCycle(75)
    pwmB.ChangeDutyCycle(25)
    GPIO.output(in1_pin, False)
    GPIO.output(in2_pin, True)
    GPIO.output(in3_pin, False)
    GPIO.output(in4_pin, True)

def turnRightReverse():
    pwmA.ChangeDutyCycle(75)
    pwmB.ChangeDutyCycle(25)
    GPIO.output(in1_pin, True)
    GPIO.output(in2_pin, False)
    GPIO.output(in3_pin, True)
    GPIO.output(in4_pin, False)

def spinLeft():
    pwmA.ChangeDutyCycle(100)
    pwmB.ChangeDutyCycle(100)
    GPIO.output(in1_pin, True)
    GPIO.output(in2_pin, False)
    GPIO.output(in3_pin, False)
    GPIO.output(in4_pin, True)

def turnLeftForward():
    pwmA.ChangeDutyCycle(25)
    pwmB.ChangeDutyCycle(75)
    GPIO.output(in1_pin, False)
    GPIO.output(in2_pin, True)
    GPIO.output(in3_pin, False)
    GPIO.output(in4_pin, True)

def turnLeftReverse():
    pwmA.ChangeDutyCycle(25)
    pwmB.ChangeDutyCycle(75)
    GPIO.output(in1_pin, True)
    GPIO.output(in2_pin, False)
    GPIO.output(in3_pin, True)
    GPIO.output(in4_pin, False)

def stop():
    GPIO.output(in1_pin, False)
    GPIO.output(in2_pin, False)
    GPIO.output(in3_pin, False)
    GPIO.output(in4_pin, False)
    pwmA.ChangeDutyCycle(0)
    pwmB.ChangeDutyCycle(0)

#Setup window, set cam image to background
pygame.init()
pygame.camera.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("DaBot")
pygame.mouse.set_visible(8)
pygame.key.set_repeat(100, 100)
#cam = pygame.camera.Camera("/dev/video0", (384, 288))
#cam.start()
#background_image = cam.get_image() #pygame.image.load("eyes.jpg").convert()
#screen.blit(background_image, [0,0])
pygame.display.update()


try:
    while True:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == 273 or event.key == 278: #up arrow or Home
                    forward()
                elif event.key == pygame.K_s: #s key -> straight line test
                    forward()
                    time.sleep(3)
                    stop()
                elif event.key == pygame.K_p: #p key
                    GPIO.cleanup()
                    break
                elif event.key == 274 or event.key == 279: #down arrow or End
                    reverse()
                elif event.key == 276: #left arrow
                    spinLeft()
                elif event.key == 277: #Insert
                    turnLeftForward()
                elif event.key == 127: #Delete
                    turnLeftReverse()
                elif event.key == 275: #right arrow
                    spinRight()
                elif event.key == 280: #Page up
                    turnRightForward()
                elif event.key == 281: #Page down
                    turnRightReverse()
                else:
                    print (event.key)
#                im = get_image()
#                background_image = pygame.image.frombuffer(im.tostring(), im.size, im.mode)
                background_image = pygame.image.load("eyes.jpg").convert()
                #background_image = pygame.transform.rotate(background_image, 90)
                screen.blit(background_image, [0,0])
                pygame.display.update()
            elif event.type == pygame.KEYUP:
                stop()
     
#    speed = int(cmd[1]) * 10
#    print(speed)
#    pwm.ChangeDutyCycle(speed)

except(KeyboardInterrupt, SystemExit()):
    GPIO.cleanup()
#    cam.stop()
 I left in the camera stuff this time. Most of it is commented out, but some isn't. I just wanted to show, basically, the works there. At a leter date, when I get a camera that works with pygame, I will return to it. For now, we are just interested in the movement.
For the most part, much of this will look fairly familiar. A couple of changes you may have noticed, are the Turn functions. Spin is great, turns on a dime, gets you where you are going, and tears the tracks right off the wheels. Which, of course, leaves the bot high and dry. I found that if the robot drives forward and turns instead of just spinning, it keeps the tracks on. I also added another set of forward/reverse keys. This allows you to move your whole hand up the the "turn" keys, lowering the chance of spinning or turning when you don't want to.

Those with a keen eye may have noticed pwmA and pwmB. These are the PWM pins. Remember way back when I said leave the jumpers in place on the enable pins? Well, I removed those. I then connected them to my PWM pins. Setting the PWM pins to 100 is the same as those jumpers. However, we can now set those to lower values, basically giving us a throttle. This is what makes the Turn functions a reality. Without PWM we are stuck either all on or all off. Now we can vary it. So, 75% on one side 25% on the other, abracadabra, we turn. Without losing our tracks. I also cut the reverse power to 50%. Why? Just to test. Later, I will add input variables to adjust the speed of the functions. But for now they are proof of concept.

I now have all the tools I need to make my robot drive itself. All I need is a way for it to know where it is going. A Distance Sensor. I have a sonic one on its way, I have the code written, I even have a cable spliced with resistors waiting for a quick connect. As soon as it gets here, I will be sure to update you all.

In the meantime, I wasn't super happy with pulling my cable out of my battery pack after I shut down the Raspberry Pi. So, since I had an extra switch from the motor battery pack, I decided to add it to a USB cable to give the Pi a switch as well. I will do an aside soon to show how to set that up.

Until then, keep building!

Monday, August 10, 2015

Almost mobile

 Previously I showed you how I built the lower chassis, which held the drive train components. Today, I am going to talk about the upper level, which holds the Raspberry Pi, temporarily, a camera, and, eventually, a battery.
Let us do this!
<!--more-->
 As you can see, the top is wider than the bottom. A full 1.5" wider to be exact. This is because I wanted to cover the tracks from above. The end project will have enclosed tracks, and this let me get a better feel for the space. The top is also an inch shorter. This is because, while I aligned the back, I wanted the front to sit back a little. This was a purely aesthetic choice, but it will allow me to place the distance sensor at the front and run the wires over, instead of through. The wires for the drive train run through a hole in the top center. That is the spaghetti mess you see on top. I am still waiting for my female to female and female to male connectors.

After I cut the top to size, I drilled holes in the bottom and top levels, through which I could run 2" bolts. I ran them nuts up to cut down on objects underneath that are likely to catch. I then made a space using some brass tubing. While doing this, keep in mind where your axles are and plan accordingly.
It is hard to see in this picture, but I also added a power switch to the battery pack for the drive train. Like I said last time, I wanted to have the motors and Pi powered separately. This switch lets me easily turn off the motor while I am just using the Pi, saving on my batteries. It also lets me quickly turn off the motor in the event of a program crash, which can tend to leave the motors running. More on that later.

 I also experimented with an old digital camera I had laying around. This thing has never been very useful. It was cheap, but never really worked real well. However, it seems to do alright as a webcam.

I stripped off the plastic case, keypad, and little screen. They won't be needed for this application, and they were just more weight and power draw. I did add its own two AA battery power supply. This only seems necessary when starting up the camera, as it will continue to run on just the Pi's power from the USB. I then plugged it into the USB, installed fswebcam, and took a couple pics.

However, when I tried to add it to my program, things failed. It seems PyGame won't read from the camera directly. It can't start the device. I found a work around by having fswebcam take new pictures continuously. As the goal was and is to only take pictures while it is moving, under the assumption that, while sitting still, new pictures aren't really needed, this is just an extra CPU tax. There is also a problem when the program grabs the picture. Sometimes it will grab partway through the snap, getting a partial image. Sometimes it will flat crash with a non-acceptable file error. At which point, the robot keeps doing whatever it was doing. Hence the usefulness of the motor power switch. Most of the time I just run it with the camera off or not even attached, just loading the image that was last taken. Not the coolest, but it works.

Next time I will have my battery to power my Pi and can finally be free. Currently, I am running with wall power and just hook up a keyboard directly. In this way, I have a keyboard cord and power cord hanging off, like some sort of umbilical. This seriously hampers movement. Many times the cords will just pull the Pi right off the top.

Until then, keep building!

Friday, August 7, 2015

The Chassis

 Now that I had a working motor setup, I needed a way to hold it all together. For this I built a test bed body. I plan to 3D print a final body when I have a better idea what goes into the robot, so that I will have room and a better placement design. As the chassis is pretty simple, this is a post you can probably skip. If not, read on.
<!--more-->
The base for the chassis is an old sign I snagged from work. It is some kind of fiber board, with a bit of plastic in it, I think. It is light and really flexible. I folded it nearly in half and couldn't snap it. This will be great for my robot, though I hope it won't get folded in half. However, if you don't have access to crazy materials, MDF Hardboard will work great. Heavier thicker boards would work, but weight down on the motors. Acrylic sheets would also work, and have a fairly cool finished look.

As I mentioned before, I used the Tamiya double gearbox and track & wheel sets. As such, some of my design was already decided. Width was set at 3", because that would be the space between the hubs of my wheels, using the supplied axles. I made it 8" long, as I had figured out that with the configuration I wanted, that was about as long as I wanted it, so that I had minimal over hang in front and back of the wheels. I found this by cutting the sheet I had into a 3" wide board. I then laid out the tracks to roughly gauge where everything would go, and how long I would want it.

I then cut strips to make grooves for the axles on the wheels. As the wheels are free moving, that meant my axles didn't need to be super free to spin. If you are using wheels that lock to the axles, you will need to make sure the axles can spin, and I recommend using some way of lubricating and possibly even bearings. For this early setup, the plastic wheels around a metal axle is fine for my purposes.

For the front axle, which was going to have bigger wheels and I wanted to be higher, I built a slightly different setup. The axle will run a a full width channel, giving it greater strength, and creating a small mounting platform for my future distance sensor. You can see better in this image than in the last, where I cut larger space for the wheels hubs to fit. The wheel kit I have has hubs that stick out on the inside. If I didn't want to give up more space for the wheels, I had to accommodate.

Here is the base chassis with the wheels attached. It is hard to see here, but the front wheel is slightly up from the others. It is really only visible when it goes over anything. You can also see that the front wheel sticks out from the base. This is to allow it to do some climbing, which it is surprisingly good at. Had I not done so, the base would hit the object and stop it dead. As you will see later, the back does not stick out, and so it can get caught. Especially with some screws added later.

No it was time to add all of the movement components. The bottom "level" will house the motor, motor controller, and battery pack for the motors. A more adept robotics engineer would hook all of the power to one source, but that isn't me. Also, I want to be able to run the Raspberry Pi without turning on the robot.

Next time I will go into the upper level, putting it all together, and making it "mobile." Until then, keep building!

Monday, August 3, 2015

Almost from the beginning


I said I wouldn't start from the very beginning, skipping the learning GPIOs and what not. Apparently, I am also going to skip my ugly first steps into using an H-bridge controller. And it was ugly. I had tried making my own l298n controller, but wasn't able to get it working. I purchased a cheap l298n from China off of eBay.  When it finally arrived, I hooked up straight away to my two scavenged motors and a scavenged two AA battery pack. I could run one or the other, but not both. So, off to RadioShack to grab a power pack. From this I was able to get movement. I had always planned to run a tracked robot, and while I was at a local Hobby Town (they specialize in RC among other things), I found a Tamiya track set, as well as a Tamiya Double Gearbox. This allowed me to put together the above setup. I will discuss the gearbox and tracks in a later post. As you can see, I was still using a breakout and a breadboard. This is a great place to test on, but I scrapped it later in favor of cleaner wiring. You can also see some ribbon cable slapped in there. From my early days of computer building, I have plenty of these IDE cables lying around. However, these were just as messy, and when I finally received my male to female and female to female jumpers, I swapped them out. At some point I may come back to a full plug to easier add and remove my Pi.
The H-bridge is fairly easy to hook up. Choose 4 GPIO pins, in my case 17, 18, 21, and 22. Connect these to In 1,2,3, and 4. I left the jumpers on the enable pins, as I wasn't up to PWM for this yet. Then connect the ground of the H-bridge to the Pi AND your battery pack. Connect the batteries positive(red) to the VCC. I had attached the 5v, but a larger battery pack reset my Pi. Then connect the outs to your motors. One set to one motor, the other to the other motor. Order is less important here, but 1 and 4 to the left side of the motors and 2 and 3 to the other sides makes it easier to spin them correctly in the code.
At some point I should learn to make wiring diagrams, but at the moment, that is not today.

Here is my initial code to run things:
import RPi.GPIO as GPIO
import time

in1_pin = 17
in2_pin = 18
in3_pin = 22
in4_pin = 23
x = True

GPIO.setmode(GPIO.BCM)

GPIO.setup(in1_pin, GPIO.OUT)
GPIO.setup(in2_pin, GPIO.OUT)
GPIO.setup(in3_pin, GPIO.OUT)
GPIO.setup(in4_pin, GPIO.OUT)


GPIO.output(in1_pin, False)
GPIO.output(in2_pin, False)
GPIO.output(in3_pin, False)
GPIO.output(in4_pin, False)

def clockwise():
    GPIO.output(in1_pin, True)
    GPIO.output(in2_pin, False)
    GPIO.output(in3_pin, True)
    GPIO.output(in4_pin, False)
    print("Clockwise")

def counter_clockwise():
    GPIO.output(in1_pin, False)
    GPIO.output(in2_pin, True)
    GPIO.output(in3_pin, False)
    GPIO.output(in4_pin, True)
    print("Counter clockwise")

while x:
    cmd = raw_input("Command, f/r 0..9, E.g. f5 :")
    direction = cmd[0]
    if direction == "f": #"Forward"
        clockwise() #I used clockwise/counter to test direction, then match
    elif direction == "s": #Stop/exit loop
        x = False
    elif direction == "r": #"Reverse"
        counter_clockwise()
    else:
        print ("Invalid input")
    speed = int(cmd[1]) * 10
GPIO.cleanup() #Needed to release the GPIO and stop motors

Fairly simple. I used pins 17 and 18 for one side and 22 and 23 for the other. I then had a simple command input to move forward and back. As my code was an extension from a previous attempt to build my own bridge using just the L298n chip, I also had input for speed. I removed all of that code to nix confusion, but that part of the input is still there. At this point and for a bit longer, I won't be using PWM. I am going full on, full off, and just using the enable jumpers that came on the L298N bridge for 100% PWM. When I get my robot to working remotely, then I will worry about PWM. For right now, I am happy that I can move my wheels forward and back. Be sure to note which way the motors spin, so that you can later alter the code to make the robot move how you want. Mine is a little backwards, and 2 and 4 are forward, while 1 and 3 are backwards. The way to fix this in the hardware would be to switch the motor connections, but I have just chosen to code them that way.