I cant think of a good name, but im sure theres a good one somewhere, if any of you think of anything let me know.
Laser Cat
The idea of this project is to help me learn a few things needed for my longterm project Airborne bot. It is basicaly a laser controlled by an arduino using two servos. It is for my two cats Harry and Fifi (girls cat. Fifi ffs! ) to play with.
WHen it is complete it will enable me to move the laser using a web page with a control panel and a video feed the user will click a position on the video feed and the laser will move to that point with the cats chasing it. Each time a cat manages to hit the laser point with its paw it will gain a point. THe first one to ten will get a treat which will be thrown to it from the unit.
Im using processing to build the control panel for it to process the image from the camera and send serial output to the arduino to give the servos their position. The scoring will be worked out by dividing the target wall up into paw sized grid blocks. I think i can work out whether the cat has scored by working out if there is a change in color in the wall in that grid and if the grid thats changed is the one that the laser is in at the time, my theory is that thelicght cream wall with eiher go ginger or black letting me know which cat got the point. Possible problems that i will have to work round is differentiating between cat paw color change and laser color change.
So far i have the base unit built so that i can lay some code down, and i have the video feed going to processing and being displayed on screen. The servo is able to move along the x axis controled by mouse clicks. However im finding it difficult to control two servos through serial communication.
Eventually i plan to have the unit completely wireless and mounted in the garden.
The aims of this project are to help me gain a better understanding of the following areas:
serial communication
working with coordinates
controling things with processing
working with video
wireless communication
Update 13/ april/ 09
Ive finaly finished writing the code for the control of it. Unfortunatly i have played with it so much that my ginger cat is frustrated with it and the black cat isnt here so i cant post a video of them playing with it yet.
Here is the arduino code:
#include <Servo.h>
Servo myservo1; // create servo object to control a servo
Servo myservo2;
int userInput[3]; // raw input from serial buffer, 3 bytes
int startbyte; // start byte, begin reading input
int pos = 0; // variable to store the servo position
int i; // iterator
void setup()
{
// attaches the servos on pin 9 and 10 to the servo object
myservo1.attach(9); //x axis
myservo2.attach(10); //y axis
Serial.begin(9600);
}
void loop()
{
// if the buffer has the right ammount of data in it
if (Serial.available() > 2) {
//read the first byte
startbyte = Serial.read();
// if it's really the startbyte (255)
if (startbyte == 255) {
// then get the next two bytes
for (i=0;i<2;i++) {
userInput[i] = Serial.read();
}
// first byte is the servo we want to move
int servo1 = userInput[0];
// second byte = which position?
int servoPosition1 = userInput[1];
// print some debug lines to the serial port
Serial.print("Servo: " );
Serial.print(servo1);
Serial.print(" Move: ");
// map the input from the serial port to the min and max for the
// camera width
servoPosition1 = map(servoPosition1, 0, 179, 78,108);
Serial.print(servoPosition1);
myservo1.write(servoPosition1);
}
//repeat for servo 2
if (startbyte == 254) {
// then get the next two bytes
for (i=0;i<2;i++) {
userInput[i] = Serial.read();
}
int servo2 = userInput[0];
// second byte = which position?
int servoPosition2= userInput[1];
Serial.print("Servo: " );
Serial.print(servo2);
Serial.print(" Move: ");
Serial.print(servoPosition2);
servoPosition2 = map(servoPosition2, 119, 1, 54, 78);
Serial.print(servoPosition2);
myservo2.write(servoPosition2);
}
}
}
I need to neaten the code up a bit and correct an error with recognising which server to move, but it works.
Here is the processing code:
import fullscreen.*;
import processing.serial.*;
import processing.video.*;
FullScreen fs;
Serial port;
//set up a few settings for the gui. you need to change this to the
// screen resolution you are using
int scrnWidth=1024; //width of screen, full screen comming soon!!
int scrnHeight=768; //height of screen
int camSizeX=640; //width of cam box
int camSizeY=480; //height of cam box
// layout settings.
int leftMargin = round((scrnWidth - camSizeX) / 2);
int camPosX=leftMargin;//x coordinate of top left corner of camera box
int camPosY=0;//y coordinate of top left corner of camera box
int textOffsetX=leftMargin + 0;
int textOffsetY = camSizeY + 5;
// serial in variables to hold any values given back from the arduino
String returnText="";
Serial myPort; // The serial port
Capture cam;
int inByte =0;
int read=0;
void setup()
{
size(scrnWidth, scrnHeight);
// Create the fullscreen object
// fs = new FullScreen(this);
// enter fullscreen mode
// fs.enter();
cam = new Capture(this, camSizeX, camSizeY);
//set up the text settings
//sets the port to the one your arduino is using
myPort = new Serial(this, "COM3", 9600);
}
void draw()
{
PFont font;
font = loadFont("Verdana-48.vlw");
textFont(font);
background(32, 62, 22);
//guideLines();
camDisplay(); //put cam on screen
mousePos(); // put mouse pos on screen
//drawGrid();
while (myPort.available() > 0) {
int gb = myPort.read();
char fg = char(gb);
println(fg);
String inBuffer = myPort.readString();
if (inBuffer != null) {
println(inBuffer);
returnText=inBuffer;
}
// text("Recieved", 5, 482);
//text(inByte, 220, 482);
}
}
void mousePressed() {
fill(6, 191, 41);
int posNewX = round( 179 - (mouseX - 190) / 3.6 ) ;
int posNewY =mouseY / 4;
char c = char(255);
myPort.write(c);
myPort.write(char(1));
myPort.write(posNewX);
text( "Here:" + posNewX, 5, 560);
char d = char(254);
myPort.write(d);
myPort.write(char(2));
myPort.write(char(posNewY));
text( posNewY, 5, 540);
}
void mousePos(){
fill(6, 191, 41);
textSize(14);
text("mouseX: " + mouseX + " / " + "mouseY" + mouseY, textOffsetX, camSizeY-10);
//text(mouseX, 210, 510);
int msPo=179 - round(mouseX / 3.6);
text("sent " + msPo, textOffsetX, camSizeY + 20);
text(returnText, textOffsetX, camSizeY + 40);
//text("mouseY", 5, 441);
//text(mouseY, 210, 441);
}
void camDisplay(){
if (cam.available() == true) {
cam.read();
image(cam, camPosX, camPosY);
// The following does the same, and is faster when just drawing the image
// without any additional resizing, transformations, or tint.
//set(160, 100, cam);
}
}
void guideLines(){
stroke(240, 17, 17);
line(78, 0, 78, scrnHeight);
line(108, 0, 108, scrnHeight);
}
void drawGrid(){
stroke(36, 137, 48);
for (int i = 10; i < scrnWidth; i+=10) {
line(i, 00, i, scrnHeight);
//line(i, 0, i, 150);
}
for (int i = camPosY; i < camPosY + camSizeY + 10; i+=10){
//ne(0, i, scrnWidth, i);
line(camPosX, i, camSizeX, i );
//line(i, 0, i, 150);
}
}
To get processing to pic up my cam i had to install vdig, there are ways to do it without vdig though, see the processing.org site for details.
As soon sd my cat gets in i will post a video , in the meantime im going to tidy my code up.
This is a companion discussion topic for the original entry at https://community.robotshop.com/robots/show/update-laser-cat