Project Description
The white box has white waves inside and a boat, looking like the boat is in a lake or ocean. When the boat moves forward. When the boat inches forward, strange things happen. If you move the boat halfway down the slider, Nessie’s head pops up and she stares at you, blinking her eyes and waiting for you to make the next move. If you move all the way to the end, Nessie will dive underwater and reappear above your boat, ready to attack. If you move back, she returns to where she came from, happy that the intruders are gone. If you only move a little bit forward, Nessie will call for backup and try to intimidate you into leaving her alone. I guess you can say Nessie’s a bit cranky today but how would you feel if a stranger came into your bedroom and started causing a ruckus?
Progress Photos
Early idea sketches of what we wanted to do, back when the objective was to reverse a switch to its default state.
Attaching the heads onto the servos after the they’ve been screwed onto the servo mounts designed to keep them in place while in the box.
Testing Nessie after the servos and boat were glued to the box. During this stage, we realized rotating her head enough to push the boat back would rip the Servo from the ground of the box so we adjusted the plan for her react to the boat location. Hidden state on the first image, attack state on the second image.
Super-gluing the rest of the waves to finish Nessie’s home.
Schematic
Code
/* * * 60-223 Project 1 Code * by Rolando Garcia III (rolandog) and Lexi Yan (yany1) * * Date: 9/14/18 * */ #include<Servo.h> #define SLIDER A0 #define BODYEYE 4 #define HEADEYE 5 #define BODYSERVO 10 #define HEADSERVO 11 Servo bodyServo; Servo neckServo; int previousDistanceFromWater; int timeAnimationBegan = 0; int animationDelay = 0; void setup() { // put your setup code here, to run once: Serial.begin(9600); bodyServo.attach(BODYSERVO); neckServo.attach(HEADSERVO); pinMode(BODYEYE, OUTPUT); pinMode(HEADEYE, OUTPUT); pinMode(SLIDER, INPUT); bodyServo.write(0); neckServo.write(0); delay(500); } void loop() { //Record the current time int now = millis(); //Check how close the boat is to the water int distanceFromWater = analogRead(SLIDER); //Check if the previous animation has completed if( (now - timeAnimationBegan) > animationDelay || (previousDistanceFromWater < distanceFromWater) ){ //Reset the timer if we are beginning a new animation timeAnimationBegan = now; //If the boat is closest to the water if(distanceFromWater < 100){ //Delay animationDelay = 1000; //Move the body all the way around & blink eye on body bodyServo.write(180); digitalWrite(BODYEYE, HIGH); delay(500); //Move the head most of the way around & blink eye on head neckServo.write(90); digitalWrite(BODYEYE, LOW); digitalWrite(HEADEYE, HIGH); delay(500); //Blink the eye a couple of times animationDelay += 700; digitalWrite(HEADEYE, LOW); delay(500); digitalWrite(HEADEYE, HIGH); delay(200); } else if(distanceFromWater < 500) { //Delay animationDelay = 2100; //Move the body very small amount, make sure the head doesn't appear neckServo.write(0); delay(100); bodyServo.write(90); delay(500); //Blink the eye and hold there for a bit digitalWrite(BODYEYE,HIGH); delay(250); digitalWrite(BODYEYE,LOW); delay(250); digitalWrite(BODYEYE,HIGH); delay(250); digitalWrite(BODYEYE,LOW); delay(250); } else if(distanceFromWater < 750) { //Delay animationDelay = 3000; //Move the body small amount + blink eye on body bodyServo.write(90); digitalWrite(BODYEYE, HIGH); delay(500); //Move the body back bodyServo.write(0); delay(1000); //Move the head up + turn on eye on head + turn off eye on body neckServo.write(90); digitalWrite(BODYEYE, LOW); digitalWrite(HEADEYE, HIGH); delay(500); //Move the body back neckServo.write(0); delay(1000); digitalWrite(HEADEYE, LOW); //Reset head and body when boat returns back to start } else { neckServo.write(0); digitalWrite(BODYEYE, LOW); digitalWrite(HEADEYE, LOW); delay(250); bodyServo.write(0); delay(250); animationDelay = 500; } //Record the last distance from the water read previousDistanceFromWater = distanceFromWater; } }
Final Images
Discussion
This project was not difficult in a technical sense, but relatively difficult in terms of usability. Lexi wanted to keep the project once it was done, so it had to be designed to be a rugged as possible. We had to use external battery power for the Arduino and our servo motors, which required soldering a battery pack into our circuit. Two different voltage sources meant that we had to tie all of our grounding together. This was the source of our biggest headache. We believed that grounding to the servos’ power source was enough, but it caused strange behavior in our sliding potentiometer and servos. When we finally tied the Arduino’s ground in, the problem was solved, but not after about 45 minutes of annoyance. We also discovered while testing that it wouldn’t be possible for Nessie to push the boat back to the origin as we originally planned without causing damage and had to adjust our expectations/goals as a result, The easy part of the assignment was constructing our enclosure, since both of us had laser-cutting experience. We also had access to some interesting scrap materials, which gave our project a unique visual flair.
Ultimately, we learned the virtue of patience. Neither of us had very consistent schedules, so our work sessions had to be very qualitative. As mentioned above, hardware debugging also caused some problems that could have been fixed with some more patience in making a schematic. In the future, we would have changed this project by making it have a bit more unpredictability, through the use of more user-responsive animations for Nessie, or more sophisticated animation triggers.
Leave a Reply
You must be logged in to post a comment.