Wednesday, February 27, 2013

USB Webcam on the Raspberry Pi

I wanted to use a USB webcam to mount on the robot, and drive it using the RPi. Turns out it is pretty simple to not only drive a USB webcam, but to also stream a MJPEG video feed over a port. After plugging the webcam in, we can check to see if the device is detected:


I run Arch on my RPi, which means installing things is super easy. Someone wrote up some software to do this streaming called mjpg-streamer.

$ sudo pacman -S mjpg-streamer

Once this installs the software is relatively simple to run. The options are defined as follows:

-d - USB Webcam (or video device)
-r - Resolution
-f - Frame Rate
-p - Port Number
-w -Web directory

An example of running the software:

$ mjpg_streamer -i "/usr/lib/input_uvc.so -d /dev/video0  -r 640x480 -f 28" -o "/usr/lib/output_http.so -p 8090 -w /var/www/mjpg_streamer"

This will send the stream over port 8090. Which can be accessed via URL through the following link (where alarmpi is the IP of the raspberry pi).

http://alarmpi:8090/?action=stream

This works with browsers which can read mjpg streams. If you happen have a web-controlled servo and some tape, you can embed the stream in the website and have a rotatable webcam.


Tuesday, February 26, 2013

Robot Parts!

My DFRobot Turtle came in the mail yesterday, and I decided to document the build process. I only ran into a few hiccups along the way, so I would say it worked out rather well. Along with the robot, I also got the DFRobot motor controller to use with my Arduino Uno to control the robot. I opted for this motor controller over the ones made by Arduino simply due to cost and convenience.

ROBOT PARTS!

The documentation that came with the parts was rather sparse, it left a lot up to the user (at least with regards to the wiring). So my build is particular to how I planned on running the robot. Given the position of the DC motor mounts in the frame, I decided it would probably be easier to solder the motor wires prior to mounting them.

Motors mounted in frame
Soldered the motor wires

This is where the first hiccuped occurred. I soldered the motors wires identically. However, they are placed in the frame opposite of each other. This means that the positive rotation of each motor are opposite to each other (aka if I power them, it'll spin in circles). Luckily for me I fixed this issue without having to desolder by reversing the wire input when I connected to the motor shield. It was right around this point that Lilu decided she wanted to help.

Lilu is blissfully unaware that this robot will scare the shit out of her
With that done, the wheels, sensor mount, battery pack, and top could all be attached to the frame. 

There is a ball bearing beneath the battery pack for the third wheel
The top and switch attached
This is where the second hiccup happened. This one was less of a mistake and more of a point of confusion. After a bit of reading I had determined that when using a motor shield with these systems, it is better to provide separate power sources to the motor shield and Arduino. Okay, I could build a 9V adapter to power the Arduino. One more thing, in order for the electrons to be happy, the power sources have to be hooked up to the same ground. I had to think about this for a bit, but essentially this means I had to take the negatives of the 9V battery and AA battery pack (grounds relative to the batteries), and put them on the same line. I also had a switch which I wanted to use with the motor shield. Given all that, I came up with a circuit design, soldered a Frankensteinian four-ended cable, and wired it up.

Circuit for power to the Arduino and motor shield
I'm going to claim over and over that I am far from a good electrician.  
I had to make the 9V adapter at the end of the four-pronged cable. Remember to put all the caps and heatshrink on the wires prior to soldering everything, this issue plagued me a number of times...

Making the 9V adapter for the Arduino

I also had purchased a really nifty prototyping plate for the top of the robot which would allow for easier configuration of components (for my future plans).

Nifty right?
Once all the wires were hooked up to the right power I ended with something which seemed to look like a robot.

Robot! =D
Finally, to test it, I used the following Arduino sketch. There are four pins which control the motors, two for each motor. One pin controls the speed via a PWM signal, the other is a digital signal which tells the motor controller to reverse the signal (make it spin backwards). This code will gradually ramp up the speed of the motors, while rotating the wheels in opposite directions.

//LEFT WHEEL
int E1 = 10;  
int M1 = 12; 

//RIGHT WHEEL
int E2 = 11;                      
int M2 = 13;                        


void setup() {
    //Setup pins for output
    pinMode(M1, OUTPUT);   
    pinMode(M2, OUTPUT); 
} 
 
void loop() {

  //Track Value 
  int value;
  //Increase PWM value each step
  for(value = 0 ; value <= 255; value+=5){ 
    //Spin forward on left wheel, and backwards on right
    digitalWrite(M1, LOW);   
    digitalWrite(M2, HIGH);  
     
    //Write speed
    analogWrite(E1, value);   //PWM Speed Control
    analogWrite(E2, value);   //PWM Speed Control
    delay(30); 
  }  
}


I noticed that one motor seemed to spin a little faster than the other even with the same signal. I am not sure if this is an electrical or software issue, or if it will even affect my goals. Here is a video of the little guy spinning.


There should be more fun to come with this robot!

Sunday, February 24, 2013

WebServo

I recently decided it would be fun to create a robot which I could control over the web (while at my office or wherever), which I could use to play with (torment) my cat Lilu. There are a few steps leading up to the creation of this. While I am waiting for the parts to arrive I started working on the web interface.

I am using an Arduino Uno as my micro controller to control the motors and servos which will be on the robot. I found ways to control the uno over the internet, however, they either require the purchase of a breakout board or USB connection to another computer. I own a couple Raspberry Pis and figured I could use what I had already to do the job. While (I think) it is totally possible to use just Arduino code to do all of this and use the RPi as the communication device, I found it more convenient given my level of understanding to simply use the RPi GPIO pins as switches for input to the Uno to trigger motor and servo control. Essentially the device will work as follows:

Web controlled robot from RPi and Uno

Since I am still (patiently) waiting for my parts. I will test my web based control using a single servo.

Raspberry GPIO control over the web

A man by the name of Eric wrote up this wonderful framework called WebIOPi, which allows for web-based GPIO control using a python-based server. The installation and usage of this framework is very simple and can be found on his site. The best part of this framework is the ability to customize the UI using the WebIOPi API.


WebIOPi Interface
I thought it would be rather neat to control the device using keyboard input. That is, the left arrow and right arrows will control the motion of the servo. I mapped each keyboard input to it's own RPi GPIO pin, so while the key is pressed the pin is high, and when released the pin is low. This was simple using some jQuery functions along with the WebIOPi API.

//Use webiopi object to initialize pins
   webiopi().read(function(){
//Init GPIO Pins 17 and 22 
     webiopi().setFunction(17,"OUT");
     webiopi().setFunction(22,"OUT");
   });

//Using the up(37) and down(39) arrows on pin 17,22.
//If key is pressed, pin goes high
   $(window).keydown(function(event){
     if(event.keyCode == 37) setValue(17,1);
     if(event.keyCode == 39) setValue(22,1);
   });
//If key is released, pin goes low
   $(window).keyup(function(event){
     if(event.keyCode == 37) setValueK(17,0);
     if(event.keyCode == 39) setValueK(22,0);
   });
//Use REST API to set pin value
   function setValueK(gpio, value){
     $.post('/GPIO/' + gpio + "/value/" + value, function(data){
            updateValue(gpio,value);                        
        });
   }
//Return data
   function updateValueK(gpio, value){
     var style = (value == 1) ? "HIGH" : "LOW";
     $("#gpio"+gpio).attr("class",style);
   }

Interface circuit for RPi and Arduino

I decided to keep the RPi and Arduino circuits isolated as I feel this would be the safest approach to combining them. This means that they each have their own power sources, which may mean the robot has a little more weight and costs a bit more, however, it means I won't have to figure out how to run it all off of one power source without frying everything. I used an opto-isolator (4n35) as a switch to provide the input for the Arduino. Using the following circuit, when the RPi pin goes high, the Arduino pin will go low. This can be detected in the Arduino code to control the servo.
Circuit diagram (apologies for the lack of standards I am no electrical engineer)

Arduino Sketch using RPi input

The Arduino sketch here is rather simple. If it detects pin 2 or 4 go low, then it will start to rotate the servo (which in this case is on pin 5). Pin 2 will rotate the servo in one direction, Pin 4 will rotate the sevro in the opposite direction.
#include <servo.h>

//Servo controller
Servo servoMain;

//Servo Definitions
int servoPin = 5;
int minP = 750;
int maxP = 2250;
int stepS = 3;
int delayTime = 20;

//Pin 2 definitions
int up = 2;
int valUp;
int bsUp;

//Pin 4 definitions
int down = 4;
int valDown;
int bsDown;

//Keep track of servo deg
int deg = 0;


void setup(){
//Init Pins
 pinMode(up, INPUT);
 pinMode(down, INPUT);

//Get inital reading
 bsUp = digitalRead(up); 
 bsDown = digitalRead(down); 

//Init servo
 servoMain.attach(servoPin,minP,maxP);
}

//Loop
void loop(){
 //Read pins
 valUp = digitalRead(up);
 valDown = digitalRead(down);

 //Only act if changed (reduce calculations)
 if ( (valUp != bsUp) || (valDown != bsDown) ){
 
  //If pin 2 is low, add the step to the servo
  if ( valUp == 0 ){
     deg += stepS;
     //Don't go past 180
     if( deg >= 180){
      deg = 180;
     }
     
     servoMain.write(deg); 
     delay(delayTime);
  }
  //If pin 4 is low, subtract the step from the servo
  if ( valDown == 0 ){
     deg -= stepS;
     //Don't go past 0
     if( deg <= 0){
       deg = 0;
     }
    
     servoMain.write(deg); 
     delay(delayTime);
  }
 }
}

Example:
      In this example I also added two buttons to the page for testing.




My Projects


I decided that it might be fun to keep a public record of all the silly projects that I've been doing.  I am terrible at keeping record of anything I do, so this will likely be poorly maintained as well. Maybe I'm just yearning to write reports again (maybe I'm just trying to find a distraction from finishing my thesis). Who knows, but hopefully I'll keep up with my records.