|
Main Links:
Final Projects
|
Main /
FinalProjectPComp Final ProjectProject Name: FrostyOmba Group Members: O V E R V I E W: Our Final Project is an interactive robot. A user is able to control the device's movement via inputs mounted on the robot. The robot is made up of two main components. The first is the platform which is a modified iRobot Roomba. The Roomba gives the robot its mobility capability. The second component is the vertical frame which sits on top of the Roomba. The frame is a modified stuffed snowman toy. P R O C E S S: Here is a picture of the roomba before any modification: ![]() Here is our Snowman prior to any modification: ![]() We first began by taking apart the Roomba to determine how to establish serial communication and how we could mount additional materials to it. Recent Roomba's come with a port that allows you to send serial command to it using a protocol published by the manufacturer. Once we were able to successfully send commands and control the Roomba's actions, we began to think about what inputs we would want from the user. We initially decided on four: Through some additional coding, we were able to integrate the direction switch into the angle input. An early success with controlling the Roomba is documented in this video. Our circuitry can be seen in this picture: ![]() Once we had the Roomba under our control, we focused on the physical interaction and shape of the unit. We stripped the Snowman down and mounted it to a wood frame: ![]() The frame bolted onto the Roomba using the its preexisting mounting brackets. We were also able to integrate the circuitry of the Snowman with our breadboard. We used the switch located on the Snowman's left hand to act as our on/off switch. As an additional feature, we placed a flex sensor inside the right arm of the Snowman. Holding his arm up or down controlled a small motor in his frame which made him stand taller or shorter. We used an H-Bridge to reverse the polarity of the motor. After dressing up the Snowman, we incorporated the three potentiometers into his body by cutting holes on the side of his body and placed the circuit in the frame of the Roomba: ![]() The final product in all his glory can be seen below and to watch a video, click here. ![]() C O D E: Below is the code we uploaded to the Arduino. It receives inputs from the three pots and then send the serial commands to the Roomba once the on/off switch is pressed. Once it has finished its sequence, it plays a song. { //ROOMBA SNOWMAN //Analog Pins int speedPot = 0; int radiusPot = 1; int timePot = 3; int flexPin = 5; //Digital Pins int goSwitch = 2; int controlPin = 3; int upPin = 4; int downPin = 5; int wakePin = 8; int testLedPin = 13; //Roomba variables byte speedHi; byte speedLo; byte radiusHi; byte radiusLo; //Input variables int go = 0; int speed = 0; int radius = 0; int time = 0; int currentFlex = 0; int previousFlex = 0; int diff = 0; //Software variables int currentState = 0; int lastState = 0; void setup() { //Set pin modes pinMode(testLedPin, OUTPUT); pinMode(wakePin,OUTPUT); pinMode(goSwitch,INPUT); pinMode(controlPin, OUTPUT); pinMode(upPin, OUTPUT); pinMode(downPin, OUTPUT); Serial.begin(57600); //Wake Roomba Up //digitalWrite(wakePin,HIGH); roombaSetMode(); //Set H-Bridge pin control mode digitalWrite(controlPin,HIGH); //Blink LED to show it is starting blinkLED(); } void loop () { roombaSetMode();
//Read flex sensor - it determines if snowman should go up or down
//First see if sensor has changed
currentFlex = analogRead(flexPin);
diff = currentFlex - previousFlex;
previousFlex = currentFlex;
//Depending on which way sensor is bent, move snowman up or down by reversing polarity on H-Bridge
if (diff > 10){
digitalWrite(upPin,HIGH);
digitalWrite(downPin,LOW);
}
else if (diff < -10){
digitalWrite(upPin,LOW);
digitalWrite(downPin,HIGH);
}
//Otherwise stop it
else{
digitalWrite(upPin,LOW);
digitalWrite(downPin,LOW);
}
//Check state of the go Switch - set flag to go or not
currentState = digitalRead(goSwitch);
if (currentState == 1){
if (lastState == 0){
go = 1;
}
}
lastState = currentState;
//If go button was pressed - read pots and move Roomba
if (go == 1){
//Read speed pot - normalize to fit Roomba values (0 to 500) only going forward here
speed = ((analogRead(speedPot) * 10)/1024) * (500/10) + 50;
//Read time pot - determines how long Roomba will move for
time = analogRead(timePot) * 20 + 100;
//Read radius pot - determines how tight it will turn
radius = analogRead(radiusPot);
//Serial.print("Pot Value = ");
//Serial.println(radius);
//Normalize radius values so that center position of pot makes Roomba go straight
if (radius > 500 && radius < 520){
radius = 32768;
}
else if (radius > 520){
radius = 4100 - (radius * 4);
}
else{
radius = - (radius * 4);
}
if (radius > 2000){
radius = 2000;
}
else if (radius < -2000){
radius = -2000;
}
//Serial.print("Radius = ");
//Serial.println(radius);
//Move the Roomba
roombaMove(speed, radius);
//Keep it moving for the specified amount of time from time pot
delay(time);
//Stop Roomba
roombaMove(0,32768);
song();
go = 0;
}
} void roombaMove(int s, int r) { speedHi = s >> 8;
speedLo = s & 255;
radiusHi = r >> 8;
radiusLo = r & 255;
if (s < 0){
speedHi = speedHi & 32767;
speedLo = speedLo & 32767;
}
if (r < 0){
radiusHi = radiusHi & 32767;
radiusLo = radiusLo & 32767;
}
Serial.print(137, BYTE); //Roomba Drive command
Serial.print(speedHi, BYTE); //Hi Byte speed value
Serial.print(speedLo, BYTE); //Low Byte speed value
Serial.print(radiusHi, BYTE); //Hi byte radius value
Serial.print(radiusLo, BYTE); //Low byte radius
} void roombaSetMode() { digitalWrite(wakePin, LOW); // Wake it up delay(500); digitalWrite(wakePin, HIGH); Serial.print(128,BYTE); //Start Roomba & puts it in passive mode // delay(50); Serial.print(130,BYTE); //Enables control of the Roomba //delay(50); } void blinkLED() { digitalWrite(testLedPin, HIGH); delay(200); digitalWrite(testLedPin, LOW); delay(200); } void song() { //Command Serial.print(140,BYTE); //Song number Serial.print(1,BYTE); //Song length Serial.print(21,BYTE); //1st quarter 1 Serial.print(71,BYTE); Serial.print(10,BYTE); //Pause 2 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 3 Serial.print(71,BYTE); Serial.print(10,BYTE); //Pause 4 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 5 Serial.print(71,BYTE); Serial.print(20,BYTE); //Pause 6 Serial.print(30,BYTE); Serial.print(20,BYTE); //2nd quarter 7 Serial.print(71,BYTE); Serial.print(10,BYTE); //Pause 8 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 9 Serial.print(71,BYTE); Serial.print(10,BYTE); //Pause 10 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 11 Serial.print(71,BYTE); Serial.print(20,BYTE); //Pause 12 Serial.print(30,BYTE); Serial.print(20,BYTE); //3rd quarter 13 Serial.print(71,BYTE); Serial.print(10,BYTE); //Pause 14 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 15 Serial.print(74,BYTE); Serial.print(10,BYTE); //Pause 16 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 17 Serial.print(67,BYTE); Serial.print(10,BYTE); //Pause 18 Serial.print(30,BYTE); Serial.print(10,BYTE); //Note 19 Serial.print(69,BYTE); Serial.print(10,BYTE); //Pause 20 Serial.print(30,BYTE); Serial.print(10,BYTE); //4th quarter 21 Serial.print(71,BYTE); Serial.print(80,BYTE); delay(10); //Play Serial.print(141,BYTE); Serial.print(1,BYTE); } } |