16-223 Work https://courses.ideate.cmu.edu/16-223/f2019/work Introduction to Physical Computing: Student Work Sat, 07 Dec 2019 09:05:37 +0000 en-US hourly 1 https://wordpress.org/?v=5.2.20 Dining Dino: Final Project Report – Edward and Quincy (12/05/2019) https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/07/dining-dino-final-project-report-edward-and-quincy-12-05-2019/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/07/dining-dino-final-project-report-edward-and-quincy-12-05-2019/#respond Sat, 07 Dec 2019 09:05:37 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4220 Abstract

Our goal was to make a dinosaur that would chew on a wooden ball and spit it out. It would be actuated by a pulley system with strings attached to horns on two servo motors, one on each side of the body. The dino would also sporadically play music.
Our final result did exactly what we promised and performed well during the museum demonstration. It attracted attention and was mostly robust, though towards the end, the wires for the servo started becoming a bit loose.
Overall, the project was very successful.

A boy plays with our project

Objectives

The main objective of our project was to create a dinosaur that would “chew” a wooden ball and then spit and “poop” it out. However, due to the compactness of our initial prototype, we decided to only focus on the spitting portion of the project rather than having both functionalities. This simplified the idea and allowed us to refine and perfect the spitting (and, thinking back, it would have taken much time to get the “pooping” to work as we wanted). Later on, we added a buzzer and found melodies on GitHub (see citations section) to allow the dino to play music and noises before it spits the ball out.

Initial prototype of the project
(finished at a responsible time and not the night before the first museum trip)

Implementation

The dino is made of 4 major pieces: one large body (with lower jaw and tail attached), an upper jaw, and two legs.
We decided on using two servo motors move the jaw up and down, which allowed for more chewing power, though, in the end, one servo would have been sufficient.
Since the structure was a bit top heavy, it naturally tipped forward, which was what we wanted. All we needed to figure out was how to get it to stand up after it leaned forward. Initially, we wanted to to have servo motors at the pivot point of the body, but we were worried that the weight of the dinosaur would harm the servo motors. So, we decided on using a pulley system to have the servo horns pull up the dino after it had leaned forward and dropped the ball. The pulley system is shown below.
The tail had a large counter weight inside it to keep the dino from leaning too fast. This weight is hidden in the final implementation.

Pulley system implementation: when the servos turn clockwise,
the body tips forward, allowing a ball placed inside to fall out.

We also had two photoreceptor sensors in the lower jaw pointing out to sense the presence of an object in the mouth. When one of them is triggered, the chew and spit sequence initiates. The sequence is: chew for a randomized amount of time, then open the mouth, play a song, lean forward, then return to standing position.

Inside the mouth: two photo-sensors aimed to sense if a ball was placed inside.

Outcomes

Our outcomes of our final demo were overall quite successful. The Dino attracted attention and held it for a decent while. The learning curve was mostly in the timing. Some people tried to feed it, while it was spitting out the balls but it was overall quite intuitive. Especially considering during the first museum demo the Dino broke down immediately, it was so relieving to see our final iteration work the whole day and survive the kids and adults who tried to play with it. We were very proud of how robust the final product was and its ability to work consistently under real world conditions.

Dino chewing and spitting out a wooden ball
A couple children engaging with our project

Future Work

The next steps for the Dining Dino would be to implement more diverse functionality. There are a few immediate fixes that should be implemented to make it more effective
First, we would make the buzzer louder. The music the Dino played was a simple last minute addition but it added a whole lot. Getting a wider range of sounds, including songs more recognizable to our target audience, would improve the fun and reward of the noisemaker.
Second, the wires we used for our pulley system will need to be secured better or converted into solid linkages so they don’t loosen over time. While this wasn’t a huge problem, we could tell by the end of the day that the base angle of the Dino was a bit lower. Having a more robust solution is an ideal upgrade.
Third, although not a huge change,  it would be quite beneficial to make our Dino a little bigger. Out on the test floor, it looked a little lost in the massive crowds. It is quite the balancing act however, because making the Dino bigger would also make it heavier and although our system was quite strong, there is a limit to how big we could go and still work effectively.
Lastly, if we had more time to work on this product, it may be a good idea to go back to the drawing board. Since we went through so many changes and iterations, the product became a plaything with a muddled conglomeration of a purpose. Taking the time to revisit what we really want to get across and how the Dino will affect people can really allow us to hone in on certain elements and push them to the max.

Final result of the Dining Dino

Contributions

Both authors made equal contributions in manufacturing the Dino: cutting parts, decorating, and testing. Edward made considerable bounds in updating code and finding online music sources while Quincy continued base testing functionality.

Final prototype functionality
CAD rendering
Simplified Circuit Schematic

Citations

Melodies – https://github.com/robsoncouto/arduino-songs

Files

#include <Servo.h&gt;

const int SEN_PIN1 = A0;
const int SEN_PIN2 = A1;

const int MOUTH_SVO_PIN1 = 8;
const int MOUTH_SVO_PIN2 = 7;
const int LEFT_LEG_SVO_PIN = 2;
const int RGHT_LEG_SVO_PIN = 4;

Servo mouth_svo1, mouth_svo2, l_leg_svo, r_leg_svo;

const int SVO1_OPEN = 80;
const int SVO2_OPEN = 100;
const int SVO1_CLOSE = 130;
const int SVO2_CLOSE = 50;

const int SEN1_THRES = 900;
const int SEN2_THRES = 900;

long chew_t = 0;
long chew_start = 0;

void setup() {
  Serial.begin(9600);

  mouth_svo1.attach(MOUTH_SVO_PIN1);
  mouth_svo2.attach(MOUTH_SVO_PIN2);
  l_leg_svo.attach(LEFT_LEG_SVO_PIN);
  r_leg_svo.attach(RGHT_LEG_SVO_PIN);

  open_mouth();
  l_leg_svo.write(70);
  r_leg_svo.write(110);
}

long start_t = millis();
void loop() {
  long curr_t = millis();

  int sen1_val = analogRead(SEN_PIN1);
  int sen2_val = analogRead(SEN_PIN2);
  
  Serial.print(chew_t);
  Serial.print("\t");
  Serial.print("");
  Serial.print("\t");
  Serial.print(sen1_val);
  Serial.print("\t");
  Serial.println(sen2_val);

  if ((sen1_val < SEN1_THRES) || (sen2_val < SEN2_THRES)) {
    if (curr_t - start_t &gt; 500) {
      start_t = curr_t;
      if (chew_t < 10) {
        chew_t = curr_t;
        chew_start = chew_t;
        close_mouth();
        delay(100);
      }
    }
  }
  else if (random(10000) == 0) {
    close_mouth();
    delay(1000);
    open_mouth();
    delay(1000);
  }
  else if (random(10000) == 0) {
    lean_forward();
  }

  if (500 < chew_t) {
    chew(curr_t);
    chew_t = curr_t;
    if (chew_t - chew_start &gt; 5000) {
      chew_t = 0;
      open_mouth();
      delay(500);
      lean_forward();
    }
  }

}

void chew(long curr_t) {
  int a = 6;
  int x0 = 55;
  mouth_svo2.write(a*sinf((float)curr_t/150) + x0);
  mouth_svo1.write(-a*sinf((float)curr_t/150) + (180-x0));
}

void open_mouth() {
  mouth_svo1.write(SVO1_OPEN);
  mouth_svo2.write(SVO2_OPEN);
}

void close_mouth() {
  mouth_svo1.write(SVO1_CLOSE);
  mouth_svo2.write(SVO2_CLOSE);
}

void lean_forward() {
  l_leg_svo.write(140);
  r_leg_svo.write(30);
  delay(random(2000, 4000));
  l_leg_svo.write(70);
  r_leg_svo.write(110);
  delay(1000);
}
]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/07/dining-dino-final-project-report-edward-and-quincy-12-05-2019/feed/ 0
Rockem Sockem – Halanna and Spencer – Final Report https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/rockem-sockem-halanna-and-spencer-final-report/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/rockem-sockem-halanna-and-spencer-final-report/#respond Sat, 07 Dec 2019 03:19:12 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4340 Authors: Halanna Yuh, Spencer Bowman

12/6/2019

Abstract

Our project was a 2-player competitive boxing game where each user controls the 2 arms of a wooden “boxer” and attempts to strike their opponent’s “boxer” in the center with the arms. Users control the arms by pressing 2 buttons that correspond to each of the arms. A sound is played when a user successfully strikes their opponent.

Objectives

  • Create a 2 player competitive game where each player manipulates the two arms of a wooden boxer by pressing the corresponding buttons with the intent of striking their opponent’s boxer with the arm
  • Each press of the button should correspond to only one strike of the arm to encourage continuous user engagement. That is, they cannot “cheat” the game by just leaving their finger on the buttons and letting their boxer strike continuously.
  • The device should have strong feedback to the user when they achieve the goal of landing a strike. This is achieved by having a sound play when a user lands a successful strike.
  • Encourage strategic coordination from users in executing and blocking strikes.

Implementation

Square force sensors were used to detect a successful strike. These sensors were chosen for this purpose because they were sensitive enough to detect the slightest touch and had enough surface area for the arm to land on when it is struck. Once the output of the force sensors decrease below a certain threshold, this indicates that the sensor is being touched, and a speaker is used to play a sound.

For the arms, we used a servo to winch in a string which was attached to both members. The members were spring loaded to naturally rest in the extended position. As the servo unwound, the slack in the string would allow the arm to return to its extended position, causing the arm to “punch”. We looked into different methods of decoupling the string from the servo so that the punch was more violent, though none of our designs were able to produce the necessary rope travel in the limited space. The punching system also allowed the arms to be stopped, or hit other punching arms without any damage to the arms or the servo. All that would happen is that the string would go into slack, and the servo will still be allowed to freely go to its desired location. The arms were put at an angle inward, so that a punch could be blocked by another punch if the used timed it right. However, if the opposing arm was not extended, your punch would land cleanly without interference. To add to the distance that we pulled in the string, we added standoffs around the outer holes of the star shaped servo horn to build a drum. We originally struggled with using glued plastic spacers as they would fall off during use. We switched to lathed down metal standoffs as we could physically attach them to the horn with a bolt through the holes in the servo horn.

Outcomes

Successes

  • Children were mostly engaged because of the game’s competitive nature. 
  • Required some coordination on the children’s behalf to block their opponent’s strike. This prompted them to become really focused on the game when engaging with it.
  • The playing of the sound gave the user a notion of success and enhanced experience.

Failures

  • Technical errors during the demo mostly involved the string snapping.
  • Sometimes the arms would become misaligned rendering the user unable to strike their opponent at all.
  • Speed of the strikes were slow due to limitations of the servo motors used.

Future Work

For future implementations, we hope to revise the fundamental experience by adding more degrees of freedom for the user to move their boxer. What could be particularly useful is providing the user with the option to move their boxer linearly along a horizontal axis so they can avoid a strike or arrange their boxer in a better position to land a strike. We could also modify the way the user executes a strike to make the experience more interesting. Instead of having the arm extend and retract with one press of the button, the user can press down onto the button to have the arm slowly retract, and then release the button to have the arm extend and strike.

Contribution

Spencer: Designed the boxer and punching mechanism. Designed and built the moving punching bag that was used for the first demo. Helped with the wiring and the code.

Halanna – Designed the button box. Assembled the wires (cutting, crimping, soldering wires to components, fitting the wires into housings). Worked on code and electronic schematic. Helped with assembly of the boxers. For the first iteration, I also worked on a linear motion system for the punching bag, although this was never incorporated in any final demos. For more information on our first iteration, refer to our Intermediate Progress Report here .

Linear motion system for the punching bag component for 1st iteration.

Video

Children interacting with the device.
A closer look at the arms.

Photo Documentation

First iteration with a “punching bag” linearly and the user attempting to strike the bag.
Final iteration at museum.

Code

#include <Servo.h&gt;
Servo arm1; 
Servo arm2;
Servo arm3;
Servo arm4;

const int SERVO_ARM1 = 8;
const int SERVO_ARM2 = 7;
const int SERVO_ARM3 = 4;
const int SERVO_ARM4 = 2;

const int SWITCH_ARM1=A2;
const int SWITCH_ARM2=A3;
const int SWITCH_ARM3=A4;
const int SWITCH_ARM4=A5;

const int FORCE_SENSOR1 = A0;
const int FORCE_SENSOR2 = A1;

const int speakerPin = 11;
bool arm1_strike = false;
bool arm2_strike= false; 

int arm1State = 0; //0 is retracted, 1 is extending, 2 is retracting
int arm2State = 0; 
int arm3State = 0; //0 is retracted, 1 is extending, 2 is retracting
int arm4State = 0; 

unsigned long int arm1Timer = 0;
unsigned long int arm2Timer = 0;
unsigned long int arm3Timer = 0;
unsigned long int arm4Timer = 0;

unsigned long int toneTimer = 0;
int toneState = 0; //0 is not playing tone, 1 is playing tone
int bagState = 0;
unsigned long int bagTimer = 0;
void setup() {
  // put your setup code here, to run once:
  arm1.attach( SERVO_ARM1);
  arm2.attach(SERVO_ARM2);
  arm3.attach( SERVO_ARM3);
  arm4.attach(SERVO_ARM4);
  //bag.attach(8);
  //bag.write(0);
  arm1.write(0);
  arm2.write(180);
  arm3.write(0);
  arm4.write(180);
  Serial.begin(9600);

}


void loop() 
{
 
  
  if(digitalRead(SWITCH_ARM1) == 0 and arm1State == 0){ //arm is retractred and button is pressed 
    arm1State = 1;
    arm1Timer = millis();
    arm1.write(180);
  }
  if (arm1State == 1 and millis() - arm1Timer &gt; 1000){
    arm1State = 2;
    arm1Timer = millis();
    arm1.write(0);
  }
  if (arm1State == 2 and millis() - arm1Timer &gt; 1000){
    arm1State = 0;
  }

  
  if(digitalRead(SWITCH_ARM2) == 0 and arm2State == 0){ //arm is retractred and button is pressed 
    arm2State = 1;
    arm2Timer = millis();
    arm2.write(0);
  }
  if (arm2State == 1 and millis() - arm2Timer &gt; 1000){
    arm2State = 2;
    arm2Timer = millis();
    arm2.write(180);
  }
  if (arm2State == 2 and millis() - arm2Timer &gt; 1000){
    arm2State = 0;
  }

  if(digitalRead(SWITCH_ARM3) == 0 and arm3State == 0){ //arm is retractred and button is pressed 
    arm3State = 1;
    arm3Timer = millis();
    arm3.write(180);
  }
  if (arm3State == 1 and millis() - arm3Timer &gt; 1000){
    arm3State = 2;
    arm3Timer = millis();
    arm3.write(0);
  }
  if (arm3State == 2 and millis() - arm3Timer &gt; 1000){
    arm3State = 0;
  }

  if(digitalRead(SWITCH_ARM4) == 0 and arm4State == 0){ //arm is retractred and button is pressed 
    arm4State = 1;
    arm4Timer = millis();
    arm4.write(0);
  }
  if (arm4State == 1 and millis() - arm4Timer &gt; 1000){
    arm4State = 2;
    arm4Timer = millis();
    arm4.write(180);
  }
  if (arm4State == 2 and millis() - arm4Timer &gt; 1000){
    arm4State = 0;
  }

  if(analogRead(FORCE_SENSOR1)< 800 and toneState == 0)
  {
    tone(speakerPin, 440);
    toneTimer = millis();
    toneState = 1;
  }
  if (toneState == 1 &amp;&amp; millis() - toneTimer &gt; 500){
    noTone(speakerPin);
    toneState = 2;
  }
  if (toneState ==2  &amp;&amp; analogRead(FORCE_SENSOR1) &gt; 1000){
    toneState = 0;
  }  

  if(analogRead(FORCE_SENSOR2)< 800 and toneState == 0)
  {
    Serial.println("tone started");
    tone(speakerPin, 440);
    toneTimer = millis();
    toneState = 1;
  }
  if (toneState == 1 &amp;&amp; millis() - toneTimer &gt; 500){
    Serial.println("tone over");
    noTone(speakerPin);
    toneState = 2;
  }
  if (toneState ==2  &amp;&amp; analogRead(FORCE_SENSOR2) &gt; 1000){
    toneState = 0;
  }  
  
 
  
}

CAD Files

https://drive.google.com/file/d/1yoQK0GaDquHBUVBWBBmlwIlKNzZ9M8Lc/view?usp=sharing

Electronic Schematic

]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/rockem-sockem-halanna-and-spencer-final-report/feed/ 0
Plinko – Final Project Report https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/plinko-final-project-report/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/plinko-final-project-report/#respond Sat, 07 Dec 2019 01:43:17 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4387 Griffin Tang & Jai Madisetty

Abstract

Our final project aimed to take the classic and simple game of Plinko and make it more engaging through kinetic systems. We chose Plinko because our previous projects produced the finding that kids love suspense, and the bulk of playing Plinko is waiting in suspense for the outcome.

Objectives

Throughout the semester, we learned several lessons about what kids find appealing in interactions, and these lessons informed our design decisions.

We also learned from previous projects that kids are more confident engaging with controls that they can understand quickly and have precedent for in the real world.

We also learned that kids love motion and learning timing, this is why we added two sweeping obstacles in the middle of the pegboard.

Implementation

As per the lessons learned, we wanted our game to begin with a physical input, which took the form of a hammer action that kicks off the game by launching the disc into the pegboard. We initially had the direction react to where the puck was coming from, but found that it took some time for the kids to understand what was happening.

When considering the system’s response to outcomes we looked at many possibilities and found that sound was great, but hard to keep consistently audible in hectic environments. We opted for the light strip with a sound accompaniment such that it would not be environmentally dependent, but also because it has a very large and alluring presence and a lot of adaptabilities.

Outcomes

We had a lot of fun at the museum. It was really interesting to see the different ways the children interacted with our project. One child was obsessed with the hammer mechanism. There was one child who didn’t understand that the spring-hammer system and instead of releasing the hammer after pulling it back, pushed the hammer back to hit the disk. Another child was intrigued by the tone playing, and inserted the disk from the bottom so that it would always play a sound.

We were able to retain the children who interacted with machine for a lot longer than our first iteration. We also did not have any of our pieces break off which we were a little concerned about given we used a considerable amount of superglue.

Unfortunately, towards the end of the trip, part of our hammer mechanism broke. Additionally, we ran short of time and were not able to implement a mist maker with our machine. Such a device would have been of great appeal to children.

Future Work

With more time, we definitely would have wanted to refine the form factor both aesthetically and in terms of mechanical robustness. We would’ve liked to add more color to the board itself; however, the plain wood gives the board a more suitable, old-fashioned look. Additionally, we relied on superglue A LOT. With more time, we would have definitely looked to reduce the amount of superglue used.

We would have also wanted to create more dramatic outcomes and possibly more interesting obstacles amidst the pegs. In addition to having the lights stop flashing and a tone playing, we would have liked to add misters that release mist whenever the disks pass over the photoreceptor.

Contributions

Jai handled the bulk of the Plinko board fabrication while Griffin did the bulk of the electronics and the hammer mechanism. We both made it to the exhibition.

Project Video

Photo Documentation

Moving Peg Mechanism
Final Product
Launching Mechanism

Citations

https://github.com/adafruit/Adafruit_NeoPixel

Supporting Material

Source Code

#include <Servo.h&gt;
#include <Adafruit_NeoPixel.h&gt;
#ifdef __AVR__
 #include <avr/power.h&gt; // Required for 16 MHz Adafruit Trinket
#endif
#define PIN 13 // On Trinket or Gemma, suggest changing this to 1
// How many Neopixelss are attached to the Arduino?
#define NUMpixels 60 // Popular Neopixels ring size
#define DELAYVAL 20 // Time (in milliseconds) to pause between pixelss
Adafruit_NeoPixel pixels(NUMpixels, PIN, NEO_GRB + NEO_KHZ800);

const int speakerPin = 11; //Mosfet pin

const int pr1 = A0;
const int pr2 = A1;

Servo serv1;
Servo serv2;

//What we want:
//If no puck or slot 2, servo nuetral
//If puck in slot 1, servo blocks slot one path
//If puck in slot , servo blocks slot three path

//If 

int block1 = 0;
int neutral = 90;
int block3 = 180;
int delayt = 800;
int delays = 1200;
int servPos = -180;
int servMax = 180;
int servMin = 0;
int servThresh = 3;
int servDir = 0;
int servSpeed = 1;

#define  c     3830    // 261 Hz
#define  d     3400    // 294 Hz
#define  e     3038    // 329 Hz
#define  f     2864    // 349 Hz
#define  g     2550    // 392 Hz
#define  a     2272    // 440 Hz
#define  b     2028    // 493 Hz
#define  C     1912    // 523 Hz
#define  R     0


int melody1[] = {  C,  b,  g,  C,  b,   e  };
int melody2[] = { R,  C,  c,  g, a, C };
int beats1[] = {16, 16, 16,  8,  8,  16};
int beats2[]  = {  32, 16, 16, 16, 8, 8 };
int MAX_COUNT = sizeof(melody1) / 2; // Melody length, for looping.

// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 1000;
// Loop variable to increase Rest length
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES

// Initialize core variables
int tone_ = 0;
int beat = 0;
long duration  = 0;


void setup() {
  // put your setup code here, to run once:
  pinMode(speakerPin,OUTPUT);
  pinMode(pr1, INPUT);
  pinMode(pr2, INPUT);
  
  serv1.attach(8);
  serv2.attach(7);
  Serial.begin(9600);
  while (! Serial);
  Serial.println("BEGIN");
  
  #if defined(__AVR_ATtiny85__) &amp;&amp; (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.
  pixels.begin(); // INITIALIZE Neopixels strip object (REQUIRED)
}

void setServPos(){
  if (servPos < servMin + servThresh){ // if within 0-10 (coming left) go right
    servDir = 1; 
  }
  else if (servPos &gt; servMax - servThresh){ // if within 170-180 (coming right) go left
    servDir = 0;
  }
  if (servDir == 0){
    servPos -= servSpeed;
  }
  else if (servDir == 1){
    servPos += servSpeed;
  }

  serv1.write(servPos);
  serv2.write(servPos);
  //delay(5);
}
void playTone() {
  long elapsed_time = 0;
  if (tone_ &gt; 0) { // if this isn't a Rest beat, while the tone has
    //  played less long than 'duration', pulse speaker HIGH and LOW
    while (elapsed_time < duration) {

      digitalWrite(speakerPin,HIGH);
      delayMicroseconds(tone_ / 2);

      // DOWN
      digitalWrite(speakerPin, LOW);
      delayMicroseconds(tone_ / 2);

      // Keep track of how long we pulsed
      elapsed_time += (tone_);
    }
  }
  else { // Rest beat; loop times delay
    for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
      delayMicroseconds(duration);  
    }                                
  }                                
}
void playMelody(int dif){
  if (dif == 1){
    for (int i=0; i<MAX_COUNT; i++) {
    tone_ = melody1[i];
    beat = beats1[i];

    duration = beat * tempo; // Set up timing

    playTone();
    // A pause between notes...
    delayMicroseconds(pause);
    }
  }
  else{
    for (int i=0; i<MAX_COUNT; i++) {
    tone_ = melody2[i];
    beat = beats2[i];

    duration = beat * tempo; // Set up timing

    playTone();
    // A pause between notes...
    delayMicroseconds(pause);
    }
  }
}


void checkHit(){
 if (analogRead(pr1) < 250){
    //tone(speakerPin,1000);
    pixels.fill(pixels.Color(0, 150, 0));
    pixels.show();
    playMelody(1);
  }
  else if (digitalRead(pr2) == LOW){
    //tone(speakerPin,1500);
    pixels.fill(pixels.Color(0, 0, 150));
    pixels.show();
    playMelody(0);
  }
}
void loop() {
  setServPos();
  noTone(speakerPin);
  pixels.clear();
  //Serial.println(analogRead(pr1));
  checkHit();
  if (analogRead(pr1) &gt; 250 &amp;&amp; analogRead(pr2) &gt; 250){
    rainbowFade2White(0,1, 0);
    //pixels.fill(pixels.Color(100, 100, 100));
  }
  
  pixels.show();
}

void rainbowFade2White(int wait, int rainbowLoops, int whiteLoops) {
  int fadeVal=0, fadeMax=100;

  // Hue of first pixel runs 'rainbowLoops' complete loops through the color
  // wheel. Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to rainbowLoops*65536, using steps of 256 so we
  // advance around the wheel at a decent clip.
  for(uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops*65536; firstPixelHue += 256) {
    setServPos();
    
    for(int i=0; i<pixels.numPixels(); i++) { // For each pixel in strip...
      checkHit();
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      uint32_t pixelHue = firstPixelHue + (i * 65536L / pixels.numPixels());

      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the three-argument variant, though the
      // second value (saturation) is a constant 255.
      pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(pixelHue, 255, 255 * fadeVal / fadeMax)));
    }

    pixels.show();
    delay(0);

    if(firstPixelHue < 65536) {                              // First loop,
      if(fadeVal < fadeMax) fadeVal++;                       // fade in
    } else if(firstPixelHue &gt;= ((rainbowLoops-1) * 65536)) { // Last loop,
      if(fadeVal &gt; 0) fadeVal--;                             // fade out
    } else {
      fadeVal = fadeMax; // Interim loop, make sure fade is at max
    }
  }
  }

CAD Files

Electronic Schematics

]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/plinko-final-project-report/feed/ 0
Pelican: Final Project Report https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/pelican-final-project-report/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/pelican-final-project-report/#respond Fri, 06 Dec 2019 22:58:35 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4333 Abstract
For this final project, we were tasked with creating a plaything for children in Pre-K and elementary school to interact with at the Children’s Museum. We wanted to create a ping pong ball launcher under the guise of a pelican. Children would be encouraged to toss ping pong balls into the large bucket bill of the pelican which would open and close randomly so that getting the balls into the mouth would become a game. If a child successfully “fed” the pelican, the pelican would reopen its mouth and shoot the ping pong ball back. 

In order to create realize this idea, we developed two iterations over four weeks. We tested each iteration at the Children’s Museum and received great feedback.

Objectives

At the beginning of construction, there were many features we wanted to add:

  • Randomly opening and closing mouth 
  • Consistently ejected ping pong balls
  • Rapid fire launch of ping pong balls
  • Mouth will be reliably open when returning ping pong balls 
  • Points tracker
  • Sound

Design Process

Iteration 1

Implementation

Our first iteration of this idea had a working ping pong launcher and randomly opening mouth. These two portions worked well separately but did not work together cohesively. The ping pong balls ran down a track out the back of the mouth and were launched outside of the mouth. Since the ping pong ball launcher was the main feature of the device, we spent a lot of time trying to get that portion of the project to work first. Due to time constraints, although we got the ping pong launcher working, the rest of the structure became more afterthoughts and we were unable to integrate the ping pong launcher portion into the head. 

Outcomes

The children had a lot of fun playing with the plethora of ping pong balls. Instead of being compelled to throw the balls into the mouth, they would often deposit the balls directly or dump several at once.

Many children were rather rough with the pelican, and it fell apart a few times but was easily reassembled on the spot. The large head on a small body was not very stable and thus something to be improved on in the second iteration.

Iteration 2

Implementation

We designed a larger mouth and planned for spaces to integrate the ping pong launcher appropriately. Behind the bucket mouth, there was a smaller cavity where the ping pong balls were collected and then placed for launching at a higher level.

Launching mechanism

Since we added the device to move the ping pong balls to the higher level, we were required to shift how our motors were connected to the shield board. We had four motors total —  a servo for the beak, two DC motors for the launcher and an additional DC motor for moving the collected ping pong balls. We ended up wanting to control the DC motor transporting the collected ping pong balls, but the shield board only supported controlling two DC motors from DCA and DCB. However, we realized that since the launcher motors did not need to be controlled, they could simply be wired to power and ground.

We had many difficulties getting the balls to launch consistently out of the mouth. Sometimes the wheel would not pick up the ball to move it to the launcher and become jammed. In order to resolve this, we programmed the wheel to move backwards a little bit to get the ball to fall back into a better position for it to be lifted.

#include <Servo.h&gt;

#define MOT_A1_PIN 6
#define MOT_A2_PIN 5

long count;
Servo s;

int s_pin = 2;

bool backwards = false;

void setup() {
  s.attach(s_pin);
  s.write(180);
  
  pinMode(MOT_A1_PIN, OUTPUT);
  pinMode(MOT_A2_PIN, OUTPUT);

  digitalWrite(MOT_A1_PIN, LOW);
  digitalWrite(MOT_A2_PIN, LOW);
}

void loop() {
  count = millis() % 2500;
  if(count == 1800)
  {
    digitalWrite(MOT_A1_PIN, HIGH);
    digitalWrite(MOT_A2_PIN, LOW);
    s.write(180);
  }
  if(count == 1900)
  {
    digitalWrite(MOT_A1_PIN, LOW);
    digitalWrite(MOT_A2_PIN, LOW);
  }
  if(count == 0)
  {
    digitalWrite(MOT_A2_PIN, HIGH);
    digitalWrite(MOT_A1_PIN, LOW);
    s.write(rand() % 90 + 90);
  }
}

Outcomes

The children still had a lot of fun playing with our project, but this time when the balls were launched out of the mouth, it often seemed like more of a surprise to children than in the first iteration because the launching mechanism was more hidden. 

We also observed some unintended interaction with the device. The children would often try to aim for the hole in the back of the mouth that the balls were being relaunched out of instead of just aiming to throw it in the main large cavity.

This time, the pelican received little to no damage because it was built sturdier and stood on a wide base

Future Work

For a future iteration of the project, we would attempt to resolve our two main issues: the balls being launched straight back into the mouth, and the balls getting stuck and clogging the mouth. For the former, most likely a simple constraint above the launcher would force the balls out at a higher velocity, thus resolving that problem. For the latter, we would have to determine a way to empty the mouth of all the balls. To do this, there could either be a hatch on the bottom or front of the mouth that would allow the balls escape, or the bottom of the mouth could be mounted on a servo and rotated up, pushing the balls out of the top of the mouth.

Contribution

Below are the main responsibilities each of us took.

Julian: CAD, Arduino code

Sophia: designing and dimensioning on paper, wiring

Both: construction/assembly and decoration

]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/pelican-final-project-report/feed/ 0
Whale Rescue https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/whale-rescue/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/whale-rescue/#respond Fri, 06 Dec 2019 18:24:00 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4184 By Patricia Yu and Caio Araujo, Dec 6th 2019

Abstract

Our project is called Whale Rescue. We wanted to create a fun creature that would attract children with a recognizable appearance and an eye-catching movement. The primary function of our mechanism was to have an interaction where a person would want to place their hands inside the jaws of the creature and take the items inside without being caught or “bitten” by the jaw. The fear of being captured by the jaw would raise more thrill in the user and when they obtain the items in the jaw, they could appreciate it more due to the “danger” they had to go through while getting it. We chose to place small sea creature figurines inside the jaw and purposely told each child to help save the creatures inside the jaw in order to  implicitly teach children to help those in need.

Objectives

For this project, we had four main objectives in mind. First, we wanted to create an enjoyable experience for the children by making what we thought would be a fun and attractive machine for them to play with. One of the most rewarding feelings we got from our previous projects was to see children having fun when interacting with them, so we wanted to preserve that.

Second, we thought the machine should have an intuitive interface which would allow children to play by themselves with little facilitation from our side. We believed that this independence would improve the children’s experience and motivate their autonomy.

Next, we believed the playing experience should be challenging enough to incite curiosity, but not enough to be intimidating. As such, we attempted to create a gamified interaction which had both a smooth learning curve and strategy to it. The longer a child played with our project, the more often they should succeed in rescuing the fish.

Lastly, on a more technical detail, we wanted to expand our “area of sensing”. In previous iterations of the general “chomping machine”, there was a small area that the sensors were able to detect, so children could easily get around it. In this project, we believed it would be better if we could have a larger sensitive area, in order to create an experience that would be both more challenging and rewarding.

Implementation

We first designed the shape of our whale on SolidWorks and using the laser cutter created the major structure of the whale. Then we used felt to cover the exterior and its back to create a curved surface. 

For the jaw movement, we did not want to attach the laser cut jaw pieces directly on the servo horn, and instead used a pull-string method. We used a horizontal wood pole as an axle to attach the two sides of the jaw on the whale, then using twine to connect the axle and the moving servo to lift and drop the jaw. This was an improvement from using two servos attached to both sides of the jaw; it prevented the servo to overheat and melt the glue that held the jaw to the servo, the two servos from accidentally moving desynchronized, and from children forcing the jaw open or closing and breaking the servo completely. 

For the movement sensing pressure plate, we used IR proximity sensors and springs. There were two places where this mechanism was implemented: on the top of the head of the whale to sense when someone was petting it, and inside the jaw to detect when there was a hand trying to grab the contents inside. We did this by having two plywood plate placed on top of each other with four springs in between, and an IR sensor placed in the middle of the wooden plates. The sensor will be able to detect a change in light according to the proximity of a non-attached wood plate above it. For example, if a hand was touching the top plate, it would press it down, then the sensor would be able to detect a change in light and cause another reaction. 

One reaction that is triggered from the two pressure plates is the servo mentioned before into moving the jaw. The other is placed on the top of the head, where if someone pets the top of the head, it will activate a speaker that creates a tone mimicking a whale sound and the servo will turn to a larger degree, making the jaw opening wide like a yawn. 

Outcomes

We managed to achieve many of our goals, but we also learned that some parts of our project could have been better. Regarding the overall experience, children enjoyed playing with our whale, but the younger ones (around 3 years old) seemed a bit scared at first. One interesting interaction we had was that when groups of children played with the whale at the same time, they would create a competition around it without any suggestion from us. Sometimes they would see who retrieved more fish, or who got bitten less times, but they always had fun.

Concerning the technical aspects, the jaw movement was very smooth and robust. Although our mechanism relied on the string being tensioned during the entire process of opening and closing the mouth, the movement did not feel ‘blocky’ and the string did not pop during the demo. Also, since the servo was not supporting the jaw, a direct hit to the whale’s head would likely compromise the wooden structure, but the servo would not break.

Furthermore, our attempts to expand the sensitivity area by using movable plates worked well, although with some caveats. The pressure plate in the mouth was successful in detecting rushed attempts to retrieve fish, so, combined with our robust structure, the mouth plate mechanism was very consistent. The head plate, however, did not work quite well. Because of the moving nature of the opening jaw, our proximity sensor would detect changes in the distance between the two plates while the jaw was opening and closing. Therefore, while it did detect petting, it would also detect the whale’s own movement.

There were a couple more obstacles we faced. First, we forgot to consider the ambient noise of the Children’s Museum, so our speaker went by unnoticed for most of the demo. And our last mishappen was that our power source failed to provide enough current to the whale during the demo (this could have been easily avoided with earlier testing ). The 5-Volts power supply we had for the Arduino could not provide enough power to run both the servos and our speaker, thus we had to keep Caio’s laptop out to power the Arduino.

Future Work

In our next iteration of this project, we could have made the creature look friendlier and that could mean changing to an animal with a beak. The sharp teeth was something that made some of the younger children hesitant to approach it. We would also change our power source to a higher voltage because our code to allow it to function with the mechanism being plugged to a computer. For this specific project, we were in a space where there were many people and so the noise was very loud and the sound of our whale “yawning” was barely visible. Therefore, for our next iteration, instead of the whale making noises through the speaker when petted, we could add more animation in the chomping or include LED lights for more dramatic visual elements.

Contributions

For our individual contributions, we decided to split tasks according to our specific skills. Our general idea for the project came from Patricia, as she wanted to create a fun experience for the children by reimagining the interactions with her previous project, the chomping dinossaur. As a design major, Patricia worked mostly on the overall physical structure and appearance. She did most of the SolidWorks pieces and decorations. Also, she planned the aesthetics of our whale and was responsible for creating the intuitive interface of the whale.

Caio, on the other hand, worked the software and designed the general sensing and jaw structures. He wrote the code for the whale and came up with the idea of checking for differences in readings of the proximity sensor rather than detecting whether it was below a certain threshold. Also, he planned the initial design for the robust jaw structure.

After our first iteration, we tweaked the part measurements and mechanical structures together. Lastly, we both contributed to improving the initial design of the robust jaw, which did not work well since the fishing line we used kept popping.

Our Video

Our mechanism in action

Photo Documentation

The pull string mechanism where the laser cut jaws are attached to a pole that rotates. The pole is rotated by a twine (in the photo, we replaced the fishing string with twine later) connected to the servo horn.
The pressure plate held up by springs and photosensor on top of the whale’s head
The pressure plate held up by springs and photosensor inside the whale’s jaw
Whale Rescue in action being played by children

Supporting Material

CAD Files

Electronic Schematics

IR Proximity Sensors interface
The hobby servo interface
Speaker interface with a transistor serving as an amplifier

Code

#include <Servo.h&gt;

const int SERVO_PIN_1 = 8;
const int BUZZER_PIN  = 11;
const int PHOTO_PIN_1 = A1;
const int PHOTO_PIN_2 = A0;
const float open_angle1 = 130;
const float wideness = 70;
const float closed_angle1 = open_angle1 - wideness;

Servo servo1;

void reset_all() {
  servo1.write(open_angle1);
}

void slow_open(int angle, float cur1) {
  float i = 0;
  float j = 40;
  while (i <= angle){
    servo1.write(cur1 + i);
    tone(BUZZER_PIN, j);
    i += 0.25; // 0.25 and delay(10) super smooth, delay(15) also good
    j += 0.5;
    delay(15);  
  }
  delay(250);
}

void slow_close(int angle, float cur1) {
  float i = 0;
  float j = 140.5;
  while (i <= angle){
    servo1.write(cur1 - i);
    tone(BUZZER_PIN, j);
    i += 0.25; // 0.25 and delay(10) super smooth, delay(15) also good
    j -= 0.2;
    delay(15);  
  }
  noTone(BUZZER_PIN);
  delay(250);
}

void regular_open(int angle, float cur1) {
  servo1.write(cur1 + angle);
  delay(250);
}

void regular_close(int angle, float cur1) {
  servo1.write(cur1 - angle);
  delay(250);
}

void setup() {
  // put your setup code here, to run once:
  servo1.attach(SERVO_PIN_1);
  reset_all();
  pinMode(PHOTO_PIN_1, INPUT);
  pinMode(PHOTO_PIN_2, INPUT); 
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  // reset_all();
  int photo_read = analogRead(PHOTO_PIN_1);
  int photo_read_top = analogRead(PHOTO_PIN_2);
  int bite_threshold = 5;
  float now = millis();
  float yawn_threshold = 15000; // 30 milliseconds
  
  static float current_angle1 = open_angle1;
  static float last_yawn_time = 0;
  static int last_read = -1;
  static int last_read_top = -1;
  static int prev_last_read = -1;
  static int bites_since_yawn = bite_threshold;
  
  // yawn if being pet (petting detection is currently unreliable -&gt; NOT FIXED)
  if (last_read_top &gt; 0 &amp;&amp; (bites_since_yawn &gt; bite_threshold || (now - last_yawn_time) &gt; 30000) &amp;&amp; prev_last_read == last_read_top &amp;&amp; 
      abs(last_read_top-photo_read_top) &gt; 0 &amp;&amp; (now - last_yawn_time) &gt; yawn_threshold){
    bites_since_yawn = 0;
    // yawn
    slow_open(50, current_angle1);
    current_angle1 += 50;
    delay(500);
    slow_close(50, current_angle1);
    current_angle1 -= 50;
    delay(500);
    last_yawn_time = now; 
  }

  // bite if being pressured (detect difference from previous reading)
  if (last_read &gt; 0 &amp;&amp; abs(last_read-photo_read) &gt; 2){
    bites_since_yawn++;
    int angle = random(wideness-10, wideness+1);
    int chomps = random(1, 5);
    for (int i = 0; i < chomps; i++){
      regular_close(angle, current_angle1);
      current_angle1 -= angle;
      regular_open(angle, current_angle1);
      current_angle1 += angle;  
    }
    delay(725);  
  }
  
  prev_last_read = last_read_top;
  last_read_top = photo_read_top;
  last_read = photo_read;
}

Mechanical Drawings

Push-board mechanism with the chomping of the jaws
Pull-string method with the movement of the jaws
]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/06/whale-rescue/feed/ 0
Marble Maze Melody Machine https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/marble-maze-melody-machine/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/marble-maze-melody-machine/#respond Fri, 06 Dec 2019 04:49:31 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4232 By: Wenqing Yin and Hagan Miller

Submission Date: 12/5/19

(Magical Marble Maze Melody Machine Making Music Mechanically)

ABSTRACT

The goal of the project was to keep children entertained by a Marble Maze that they could interact with that provided a musical result based upon their input. The resulting maze and combination of parts do realize this goal for a period of time. The feedback from the children and adults that came by did seem to enjoy the loading gears for the maze more than the maze itself. Though when the attention did block away from the gears, the user did interact with the later parts of the maze.

OBJECTIVES

  • Create an entertaining kinetic maze system that involves marbles
  • Have the user interact with the system through marbles
  • The maze then interacts with the marbles to produce musical notes
  • Create a lift that initiates the marbles into the maze
  • Have a tilting mechanism that allows the user to computationally maneuver marbles through the maze
  • Have a modular system

IMPLEMENTATION

Electro schematic diagram

The way we incorporated sound and music elements into the machine was analog, which was letting the marbles colliding with different materials to make different sounds. There was a ramp that was divided into two sections where one side was metal rods and the other was wood dowels. Such division created a sense of purpose in tilting the maze to get the marbles to fall onto either one of the sections. The surface of the ramp was etched with lines to increase the friction.

However, it is not the only place where sound happened. The sound of the marble colliding with the walls of the maze and rolling down, the sound of the maze tilting, and even the sound of the motor collectively made up of the “melody”.

For the tilting maze, we attached the servo to the two wood sticks which exert either pulling or pushing force to both sides. There is a platform to support the semi-circle structure (there’s also another one on the other side of the maze, but not shown in the picture), which is used to support the majority of the weight of the maze to protect the servo from being destroyed.

The biggest challenges of the ball lifting structure were to reduce of the friction caused by different parts and how to scoop the ball up. We did two iterations for the ball lifting structures. The first iteration was not successful because there were too many parts causing the friction and eventually slowed down the motor. So we decided to change the way that the gears caught the balls in order to reduce the number of parts, which works at the end.

The second iteration
The first iteration

OUTCOMES

The maze was an overall success. Many children of the museum took a liking the exposed, yet complex nature of the project. Many children took an interest in the gear lift, despite it not working all the time. However, its unreliability made the children take excitement in the gambling aspect of the probability of the marble even making it to the maze. Children would even claim certain marbles and then be proud of them when they made it to the top. Some children liked and took interest in the sound ramp more as that is where the music happened. While the tilting has to be explained slightly, once accustomed, was well received. Children were consistently better at timing the machine to work more often than we were, which makes us consider that a certain slot in the gears were more likely to work than the other. The metal rod part was liked more than the wooden part, so the kids would intentionally aim for that side when the marbles approached.

FUTURE WORK

  • Increase the reliability of the ball-lifting structure
  • Test out the subsystems first  
  • Connect end to beginning, make it fully or close to fully autonomous
  • Because the overall composition is modular, we could add more components for the overall musical factor
  • Implement the sheet of copper 
  • Tuning the metal rods

CONTRIBUTIONS

Hagan Miller – Worked on the ramp back to the beginning, ramp that initialized the marbles into the gear lift, worked on the design of the maze, worked on the sound ramp, helped assemble the gears, helped in ideation

Wenqing Yin – Worked on the mechanism of the maze and the ball-lifting mechanism, worked on the button box, worked on writing the code, helped assemble the metal rods and wood dowels onto the ramp, helped in ideation

VIDEO

PHOTO DOCUMENTATION

CITATIONS

Marble-lifting mechanism:

Marble machine

Code:

https://courses.ideate.cmu.edu/16-223/f2019/text/code/CKS-Shield-1-Test.html?highlight=shield%20code

Code:

#include <Servo.h&gt;

Servo rocker;
const int MOTA_PWM1_PIN   = 5;  
const int MOTA_PWM2_PIN   = 6;
const int SWITCH_PIN  = A2;
const int SWITCH_PIN2 = A3;
const int SERVO_PIN = 8;
const int MAXANGLE = 160;
const int MINANGLE = 135;
int pos=150;
 
void setup()
{
    Serial.begin(9600);
    Serial.println("Hello!");
    rocker.attach(8);
    rocker.write(pos);
    pinMode(MOTA_PWM1_PIN, OUTPUT);
    pinMode(MOTA_PWM2_PIN, OUTPUT);

    digitalWrite(MOTA_PWM1_PIN, LOW);
    digitalWrite(MOTA_PWM2_PIN, LOW);
}
 


 
void loop()
{
  analogWrite(MOTA_PWM1_PIN,128);
  Serial.println(digitalRead(SWITCH_PIN2));
  int SWITCH_VALUE=digitalRead(SWITCH_PIN);
  int SWITCH_VALUE2=digitalRead(SWITCH_PIN2);

  // reach max angle
  if (pos==MINANGLE){
    rocker.write(pos);
  }
  if (pos==MAXANGLE){
    rocker.write(pos);
  }
 
  // if switch one is pressed, clockwise
  if (SWITCH_VALUE==0&amp;&amp;SWITCH_VALUE2!=0&amp;&amp;pos!=MAXANGLE){
    pos+=1;
    rocker.write(pos);
  }
 
  //if both are pressed, don't do anything
  else if (SWITCH_VALUE==0&amp;&amp;SWITCH_VALUE2==0){
    rocker.write(pos);
  }

  //if switch 2 is pressed, anticlockwise
  else if (SWITCH_VALUE!=0&amp;&amp;SWITCH_VALUE2==0&amp;&amp;pos!=MINANGLE){
    pos-=1;
    rocker.write(pos);
  }
 
  delay (10);
 
}
]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/marble-maze-melody-machine/feed/ 0
Katherine and Xiang: Whack-a-Worm – Final Project Report https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/katherine-and-xiang-whack-a-worm-final-project-report/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/katherine-and-xiang-whack-a-worm-final-project-report/#respond Fri, 06 Dec 2019 04:04:00 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4289 Abstract

For our final project, we decided to make a whack-a-mole game, called Whack-a-Worm. The goal is to have children hit worms with a plastic hammer that pop up from a platform and have the worms go back down, ready to come back up when called by the code. We wanted to make it engaging and attractive to the kids so they stay for a long time. We also needed the structure and mechanisms to be robust so they can endure heavy forces from the hammer. Overall, the end result was a success. The children at the museum had fun with the game, and the mechanisms held up to the end with some intervention. However we had to leave out some elements in the interest of time.

Objectives

Our goal was to create a fun whack-a-mole game. To do so, we needed to answer some conceptual and some technical questions. Conceptual questions we needed to figure out included determining what elements of whack-a-mole made it a fun game, what elements to keep and emphasize and what to change. We also needed to find what learnings, ideas, and successes from previous projects that we could incorporate into this project to make it appealing to young children. In terms of technical questions, we needed to make sure the machine wouldn’t break when hit and make sure we can complete it in a limited time. In the beginning, the features we thought were in the scope of this project was five worms, lights, and a scoreboard. However, as the project went on, we realized that not all of our goals were attainable due to time constraint, so we eventually decided to do four worms and lights.

Implementation

The most important design choice was using spring wires to help alleviate the force felt by the servo. The servo goes underneath the worm, pushing it up and letting it come down. The primary appeal of this game was the feeling of hitting something and having it react to the action. So, we focused on making the up and down motion of the worms robust and reactive. We did this by attaching spring wires to the servo horns so that when the children hit the worms, the spring wire will bend, taking most of the force instead of the servo itself.

Another design choice was using switches to sense when the worms are hit. The switches communicate with the servos, letting them know to come down when hit. There are four switches and four servos, one of each for each worm. We put the switch in between a piece of cardboard and the top layer of foam of the worm. This way, they are hidden from view, and an angry face can be drawn on the worm to make them more fun to hit. The switches and servos connected to one shield board attached to an Arduino. 

Third, we decorated our project with lights and colorful foam cutouts to make it attractive. The lights were neopixel strips programmed in different color patterns that change quickly, and we put them on the outer edge of the back of our project. The pixels were attached to another shield board and an Arduino, since they might take too much power if we attached them to the first Arduino that was already driving four large servos.

Final look – Lights in the back, worms on a platform, colorful words and designs

Outcome

Final Museum Playtest – a girl playing our Whack-a-Worm game

Our project was successful in being a fun experience for kids at the Children’s Museum. We found that the colors and lights were eye-catching, and children intuitively understood what they were supposed to do when facing the game. The project also mostly stood up to the childrens’ hitting. The key components such as the switches and the servos did not break, and we had backups for the spring wires that ended up bending due to the immense amount of force that was put on them by the children whacking the worms as hard as they could.

The main question about the success of our project lies in the childrens’ responses. There were three main types of responses that happened pretty equally. The first one was reacting to the game “correctly”. These children waited for a worm to go up and hit it down as fast as they can. They seemed to be focused on being fast. The second type was rhythmic playing. This group hit the worms that go up, but they seem to be more absorbed in the rhythm of completing a task than trying for speed. Lastly, there was violent playing, which was paying little or no attention to which worms were actually going up and only focused on hitting the worms as fast or hard as possible.

It seemed that no matter how a child played, they still had fun and were engaged with the game. This makes us think of our project as a success, even though it was less of an arcade-style game and more of a toy. During critique on Wednesday, we heard several good ideas about how to either gamify the project or run with the response we are currently getting. However, our brainstorming for future work will focus on how to gamify the project and incentivising precision and skill.

Future Work

We believe we need to include incentives to use skill in this game. One way to do so is to implement a scorekeeping system, which could decrease the amount of violent playing we saw. First, it would de-incentivise random hitting. It would also add more challenge and therefore more replayability with practice. One negative aspect of a scorekeeping system is that it could make the project less accessible for young kids. However, the scorekeeping would also add a new dimension of the game for older children, while not detracting from the experience for younger children if they ignore or do not see it.

Another element we could add is more worms and different patterns for the worms to add extra challenge. More worms could vary the kinds of movements the players make while playing, and the patterns can make the game more rewarding for those who practice more and pick up on the patterns.

Contribution

Katherine drew and laser cut parts, did most of the soldering and wiring, and designed the spring system. Xiang did the coding, decorating, and documentation. Both designed and assembled the project.

Supporting Material


#include <Servo.h&gt; 

Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;

// up down angles
int upPos = 130;
int downPos = 200;

// all switches + lists of switches and states
const int switch1= A2;
int switchState1 = 0;
bool isUp1 = false;

const int switch2= A3;
int switchState2 = 0;
bool isUp2 = false;

const int switch3= A4;
int switchState3 = 0;
bool isUp3 = false;

const int switch4= A5;
int switchState4 = 0;
bool isUp4 = false;

int listOfSwitches[4] = {switch1, switch2, switch3, switch4};
int listOfStates[4] = {switchState1, switchState2, switchState3, switchState4};
bool listOfIsUps[4] = {isUp1, isUp2, isUp3, isUp4};
Servo listofServos[4] = {servo1, servo2, servo3, servo4};
int count = 0;


void setup() {
  Serial.begin(9600);
  servo1.attach(8);
  servo2.attach(7);
  servo3.attach(4);
  servo4.attach(2);
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);

  

}


void checkHit(void)
{
  switchState1 = digitalRead(switch1);
  switchState2 = digitalRead(switch2);
  switchState3 = digitalRead(switch3);
  switchState4 = digitalRead(switch4);

  Serial.println(switchState1);
  Serial.println(switchState1);
  Serial.println(switchState2);
  Serial.println(switchState3);
  Serial.println(switchState4);

 
  if (switchState1 == 1)
  {
    Serial.println("switch 1 hit");
    servo1.write(downPos);
    listOfIsUps[0] = false;
    return;
  }

  if (switchState2 == 1)
  {
    Serial.println("switch 2 hit");
    servo2.write(downPos);
    listOfIsUps[1] = false;
    return;
  }

  if (switchState3 == 1)
  {
    Serial.println("switch 3 hit");
    servo3.write(downPos);
    listOfIsUps[2] = false;
    return;
  }

  if (switchState4 == 1)
  {
    Serial.println("switch 4 hit");
    servo4.write(downPos);
    listOfIsUps[3] = false;
    return;
  }

  
}
void raiseMole(void)
{
 int randomMole = random(0, 4);
 Serial.println("random mole is");
 Serial.println(randomMole);
 
 if (listOfIsUps[randomMole] == true) //if this random mole is already up
 {
  return;
 }
 
 //int switchState = listOfStates[randomMole]
 //int activeSwitch = listOfSwitches[randomMole]

 // raise this new mole
 Servo randomServo = listofServos[randomMole];
 randomServo.write(upPos);
 listOfIsUps[randomMole] = true;
 
}

void loop() {
  // every 2s
  count = count + 1;
  if (count == 30){
    count = 0;
    raiseMole();
  }
  checkHit();
}
// neopixel code reff'd from https://create.arduino.cc/projecthub/glowascii/neopixel-leds-arduino-basics-126d1a
#include <Adafruit_NeoPixel.h&gt;
#ifdef __AVR__
  #include <avr/power.h&gt;
#endif

#define PIN 13
#define NUMPIXELS 60

Adafruit_NeoPixel lights = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 50;

void setup() {
  // put your setup code here, to run once:
  lights.begin();
}

void turnoff(){
  for(int i=0;i<NUMPIXELS;i++){

    lights.clear();
    delay(delayval); // Delay for a period of time (in milliseconds).

  }
}

void redblue(){
  for(int i=0;i<NUMPIXELS;i++){

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    if (i%2 == 0) {
    lights.setPixelColor(i, lights.Color(0,0,150)); // blue
    }
    else {
      lights.setPixelColor(i, lights.Color(150,0,0)); // red
    }
    
    lights.show(); // This sends the updated pixel color to the hardware.

    delay(delayval); // Delay for a period of time (in milliseconds).

  }

  
}

void purpleyellow(){
  for(int i=0;i<NUMPIXELS;i++){

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    if (i%2 == 0) {
    lights.setPixelColor(i, lights.Color(150,0,150)); // blue
    }
    else {
      lights.setPixelColor(i, lights.Color(150,150,0)); // ylw
    }
    
    lights.show(); // This sends the updated pixel color to the hardware.

    delay(delayval); // Delay for a period of time (in milliseconds).

  }
  
  
}

  
}
void loop() {
  // put your main code here, to run repeatedly:
  //rainbow();
  purpleyellow();
  redblue();

}

]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/katherine-and-xiang-whack-a-worm-final-project-report/feed/ 0
Tilting Spiral Board – Omisa Jinsi and Tushhar Saha – 5th December 2019 https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/tilting-spiral-board-omisa-jinsi-and-tushhar-saha/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/tilting-spiral-board-omisa-jinsi-and-tushhar-saha/#respond Fri, 06 Dec 2019 00:28:32 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4203 Abstract

For our project, we made a tilting spiral board, in which children could press buttons to tilt the board in different directions and attempt to get marbles in the center of a spiral on the board. We wanted kids to be able to explore the contraption and gradually figure out how it works without verbal facilitation. We believed that this exploration would invoke children’s sense of creativity and innovation. On demo day, it was clear that, despite technical difficulties, children engaged well with the contraption. They quickly learned what each button represented, and how to tilt the board to get the marbles in the middle. In fact, some children were able to compete with each other using the contraption, gamifying the board even more.

Objectives

One of our main goals was to make a game which grasps the children’s attention and excites them. Other important objectives included making the entire project aesthetically pleasing, as well as making the tilts smooth and controllable. Furthermore, we wanted to implement the project in such a way that all the wires and components were integrated inside. This would make our Tilting Spiral much more approachable. The important features we focused on were the spiral, the pivot on which the board tilted, the tilting mechanism incorporating servo motors and lastly, the interface for the children.

Implementation

The big components of the project include the tilting box, the lid, the servos and the pivot. Each of these components were made out of smaller subcomponents, outlined in the paragraphs below.

For the pivot, we made a hole on the base of the tilting box which rested on a big metal pinball. The box was free to tilt around this ball. The ball in turn was attached to a box stuck to the bottom stationary layer of wood. Strings were tied from each corner of the stationary base to the corresponding corner of the tilting box to minimize rotational movement and emphasize the tilting movement.

The tilting box incorporated four rectangles with servos screwed to them. These four rectangles were diagonally spread out from the center to each corner. The servo horns are in turn attached to long levers which come out through slits in the base of the box underneath them. These levers come out and push the stationary base to tilt the box. The arduino with shield is placed around the center where all the servos, buttons and power cords are connected.

The interface included a simple set of four buttons for tilting in four directions. We realized from our first prototype that the photo-sensors were not attractive and quite complicated for the kids. Sticking to simple buttons were clearly a superior choice in terms of aesthetic and understanding. Furthermore, the order they were placed was simple and the exact pattern the kids needed to follow to win the game. This was done as the strategy to the game seemed a little hard for the kids in our first prototype run. Pressing a certain button causes two of the diagonal levers to come out and push down, resulting in the board tilting up from that side. Two servos contributing to lift the board up helped us to not overload the servos. The code used to implement this was straightforward. We received inputs from the arcade buttons. When a certain button was pressed, we would activate the corresponding two servos. We made initialized the servos at 0 degrees, and then experimented with different angles to find the right amount needed to make the board tilt.

Lastly, the lid is what implemented the game with the underlying mechanisms described above. The spiral was initially made from cardboard for the first prototype. Realizing that it did not look pretty or strong, we ended up laser cutting wood intricately to allow for bending. This was inspired by a well cut bent wooden piece in the reusable scrap. This spiral proved to be beautiful and rigid. This was stuck on top of the lid along with walls around it. Two marbles were then put outside the spiral but inside the walls. The goal of the game was to tilt the board correctly using the buttons to get the marbles to the center of the spiral which had a star.

Most of the project was assembled using wood glue and a bit of hot glue. The implications of this are discussed in the outcomes. However, we made sure to screw in the servos, as these were the components taking the load of the structure and needed to be fastened properly. As for the aesthetics, we used foam paper with spiral designs to decorate the tilting box. We also cut the name of our project ‘Tilting Spiral’ using foam paper and stuck it on the front wall of the box. Moreover, we made sure the arcade buttons were labelled properly and colorfully with arrows signifying the directions of tilt each button corresponded to.

Outcomes

Starting with the failures, on the final day of the demo, two of the levers got detached from the servo horns. This suggested that the adhesives we used for this purpose weren’t strong enough. Fortunately, there was a glue gun available for a temporary fix. One of the levers started working properly after that. However, one lever not working meant that two the directions could not be properly lifted. Therefore, with some manual facilitation, the Tilting Spiral started working like it should have. Despite the directions being labelled near the buttons, they were often overlooked. The children tried to figure out the buttons by experimenting instead of looking at the directions. Furthermore, the movement for tilting was quite rough and happened in jerks instead of being smooth like we intended. This is also be because of the unnecessarily big angle of tilt. To make marbles roll on the wood, the angle of tilt needed was much less than what we implemented resulting in rough motion of the box and the marbles.

Moving on to the successes, the purpose of the game was properly achieved. The children were able to play the game and enjoy it while it worked properly. As mentioned in the abstract, it got competitive as well. The children were trying to see who can get the marbles to the center the fastest. The children who had figured out the simple pattern were able to do so. Moreover, the designs using foam paper and the wood cut spiral certainly attracted a lot of children as well as adults, even while we tried to fix the detached levers. Even though the tilting mechanism was rough, it worked pretty well and the motion did seem appealing to the kids. Overall, the game was a certain success.

Future Work

In the future, we would like to decrease the height of the box that the ball bearing is glued on, to allow for less tilt and more smooth movement. Adding limit stoppers to limit the tilt and load on servos would also be a good idea. In addition, instead of a spiral, we would like to have a maze of the board, to make children try to problem solve a complex situation rather than pressing the same pattern of buttons to get inside the spiral. Moreover, instead of having the buttons all together, we would want to have the buttons all separated, one on each side, to make for a more collaborative and easy-to-understand experience. Furthermore, to fix the levers which were constantly getting detached from the servo horns, we would like to screw them to each other instead of using glue and tape. This would ensure secure fastening and eliminate the possibility of it coming off like it did in the demo.

Contributions

Tushhar completed most of the CAD designs as well as the soldering. Omisa worked on connecting the parts together, whether that be gluing or wiring, and crimping the wires. Both Tushhar and Omisa worked on the rest of the project together.

Videos

Omisa demonstrating how the tilting spiral works
A kid at the Children’s Museum plays with the tilting spiral board

Photos

Bird’s eye view of contraption
Inside the board – four servos along with an arduino mounted on top of the ball bearing (to avoid balancing problems)

Required Supporting Material

CAD Files: Most of the structure included boxes made from makercase.com. The levers and walls were simple rectangles. The CAD file for the spiral is attached below.

Code:

#include <Servo.h&gt;
const int SERVO1_PIN = 8;
const int SERVO2_PIN = 7;
const int SERVO3_PIN = 4; 
const int SERVO4_PIN = 2; 
const int SENSOR1_PIN = A2;
const int SENSOR2_PIN = A3;
const int SENSOR3_PIN = A4;
const int SENSOR4_PIN = A5;
Servo s1; 
Servo s2; 
Servo s3; 
Servo s4; 
int sensorValue1; 
int sensorValue2; 
int sensorValue3; 
int sensorValue4; 

void setup() {
  Serial.begin(9600);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  pinMode(A4,INPUT);
  pinMode(A5,INPUT);
  s1.attach(SERVO1_PIN); 
  s2.attach(SERVO2_PIN); 
  s3.attach(SERVO3_PIN); 
  s4.attach(SERVO4_PIN); 
  s1.write(10); 
  s2.write(30); 
  s3.write(30); 
  s4.write(30); 
  delay(500); 

}

void loop() {
  // put your main code here, to run repeatedly:
  //button2 goes to servo1 and servo2 
  sensorValue1 = digitalRead(SENSOR1_PIN); 
  sensorValue2 = digitalRead(SENSOR2_PIN);
  sensorValue3 = digitalRead(SENSOR3_PIN);
  sensorValue4 = digitalRead(SENSOR4_PIN); 
  Serial.print(sensorValue1);
  Serial.print(sensorValue2); 
  Serial.print(sensorValue3); 
  Serial.print(sensorValue4); 
  Serial.println();
  if (sensorValue1 == 0)
  {
   s4.write(75); 
   s1.write(75); 
   delay(100); 
  }
  else if (sensorValue2 == 0) 
  {
    s1.write(75); 
    s2.write(75); 
    delay(100);
  }
  else if (sensorValue3 == 0) 
  {
    s2.write(75); 
    s3.write(75); 
    delay(100); 
  }
  else if (sensorValue4 == 0) 
  {
    s3.write(75); 
    s4.write(60); 
    delay(100);
  }
  else
  {
    s4.write(30); 
    s1.write(10); 
    s2.write(30); 
    s3.write(30);
    delay(100);
  }
  
}
]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/12/05/tilting-spiral-board-omisa-jinsi-and-tushhar-saha/feed/ 0
Intermediate Progress Report – Boxing Game – Halanna and Spencer https://courses.ideate.cmu.edu/16-223/f2019/work/2019/11/06/intermediate-progress-report-boxing-game-halanna-and-spencer/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/11/06/intermediate-progress-report-boxing-game-halanna-and-spencer/#respond Wed, 06 Nov 2019 07:13:46 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4140 The concept behind the first iteration of our project was a boxing game where users control the arms of a boxer through buttons to strike a “punching bag” that moves linearly in front of the boxer.

Interaction Analysis

Interactions that were most surprising were when kids found it more enjoyable to press the buttons just to have the arms move rather than work towards the goal of having the arm strike the punching bag. Children also thought that continuously pressing the buttons would make the arms go faster, which was not the case. Additional features which would help visitors perceive more of the purpose include making the “punching bag” mechanism more legible. With the current design, it does not seem to be clear to users that the punching bag was meant to serve as a target, hence why there was less focus on striking the punching bag. The visit to the museum did not really change our final visions, but we would focus more on making components more legible to the user so that the project’s intended purpose would be more clear to them.

Engineering Analysis

A technical failure was that we were not able to get a sound to play when the punching bag is struck. Our original plan involved having a photosensor installed in the middle of the punching bag so that when an arm strikes the photosensor, a tone will play to indicate to the user that they have managed to accurately hit the punching bag. Otherwise, there were no other technical failures during the visit. Operational details that could be revised upon include creating more surface area at the tip of the arms to ensure that the photosensor is fully covered when the user manages to score a hit. We will also focus on refining some aesthetic details such as encasing exposed wires or shortening the metal rod protruding from the punching bag mechanism so it does not present as a safety hazard.

Revision Analysis

For the next iteration, we hope to revise the fundamental experience so that our project is a two-player competitive game. This would require creating another “boxer” with the same functionalities as the first one. To resolve the technical failure of the sound not working, we would need to figure out whether it is a problem with the photosensor we are using or whether it is an error in the logic of our code. A new capability that could be added includes providing the user the option to move their boxer horizontally to avoid hits by their opponent. To allow users to move their boxers, an accelerometer can be installed on the button case to detect tilt angle so that the user can tilt their cases to have their boxer move in a certain direction. We will test revision by using our finished device for an extended period of time.

Task List:

-build another boxer

-increase surface area of the tips of arms to increase likelihood of photosensor being triggered

-reach goal: implement horizontal motion of boxers

#include <Servo.h&gt;
Servo arm1; 
Servo arm2;
Servo bag;
const int SERVO_ARM1 = 7;
const int SERVO_ARM2 = 4;
const int SWITCH_ARM1=A4;
const int SWITCH_ARM2=A5;
const int LIGHT_SENSOR = A0;
const int speakerPin = 11;
bool arm1_strike = false;
bool arm2_strike= false;
int arm1State = 0; //0 is retracted, 1 is extending, 2 is retracting
int arm2State = 0; 
int arm1Timer = 0;
int arm2Timer = 0;
int toneTimer = 0;
int toneState = 0; //0 is not playing tone, 1 is playing tone
int bagState = 0;
int bagTimer = 0;
void setup() {
  // put your setup code here, to run once:
  arm1.attach( SERVO_ARM1);
  arm2.attach(SERVO_ARM2);
  bag.attach(8);
  bag.write(0);
  arm1.write(180);
  arm2.write(0);
  Serial.begin(9600);

}


float sampleLightSensor(){
  float total = 0.0;
  for(int i = 0; i < 5; i++){
    total += analogRead(LIGHT_SENSOR);
    delay(5);
  }
  return total/10;
}
void loop() 
{
  if (bagState == 0 and millis() - bagTimer &gt; 1000){
    bagState = 1;
    bag.write(180);
    bagTimer = millis();
  }
  if (bagState == 1 and millis - bagTimer &gt; 1000){
    bagState = 0;
    bag.write(0);
    bagTimer = millis();
  }
  if(digitalRead(SWITCH_ARM1) == 0 and arm1State == 0){ //arm is retractred and button is pressed 
    arm1State = 1;
    arm1Timer = millis();
    arm1.write(0);
  }
  if (arm1State == 1 and millis() - arm1Timer &gt; 1000){
    arm1State = 2;
    arm1Timer = millis();
    arm1.write(180);
  }
  if (arm1State == 2 and millis() - arm1Timer &gt; 1000){
    arm1State = 0;
  }

  
  if(digitalRead(SWITCH_ARM2) == 0 and arm2State == 0){ //arm is retractred and button is pressed 
    arm2State = 1;
    arm2Timer = millis();
    arm2.write(180);
  }
  if (arm2State == 1 and millis() - arm2Timer &gt; 1000){
    arm2State = 2;
    arm2Timer = millis();
    arm2.write(0);
  }
  if (arm2State == 2 and millis() - arm2Timer &gt; 1000){
    arm2State = 0;
  }
  
  if(analogRead(LIGHT_SENSOR)< 500 and toneState == 0)
  {
    Serial.println("tone started");
    tone(speakerPin, 440);
    toneTimer = millis();
    toneState = 1;
  }
  if (toneState == 1 &amp;&amp; millis() - toneTimer &gt; 500){
    Serial.println("tone over");
    noTone(speakerPin);
    toneState = 2;
  }
  if (toneState ==2  &amp;&amp; analogRead(LIGHT_SENSOR) &gt; 700){
    toneState = 0;
  }

  
 
  
}
]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/11/06/intermediate-progress-report-boxing-game-halanna-and-spencer/feed/ 0
Dining Dino: Intermediate Progress Report – Edward and Quincy https://courses.ideate.cmu.edu/16-223/f2019/work/2019/11/06/dining-dino-intermediate-progress-report-edward-and-quincy/ https://courses.ideate.cmu.edu/16-223/f2019/work/2019/11/06/dining-dino-intermediate-progress-report-edward-and-quincy/#respond Wed, 06 Nov 2019 06:46:51 +0000 https://courses.ideate.cmu.edu/16-223/f2019/work/?p=4117 For the first iteration of our final demo of the semester, our team deciding to create a dinosaur. The premise was a conglomeration of multiple successful projects in Demo 4, at the Children’s School. Many children were captivated by the snapping crocodile, and the game of stealing coins from its mouth. Children also took coins and tried to play with them in other projects. The notable recipient of all these coins was the very fluffy dog. Merely, the fact that it already had a hole for a mouth meant that the kids wanted to feed coins to the dog as well. Many found the idea of it eating coins and pooping them out to be hilarious and fun. So, for this project, we chose to expand on these concepts and create an exciting, holistic experience.

The goal for this project was to have a dinosaur react to wooden balls that the children would feed to it. First, a child would place a ball in its mouth (hoping not to be chomped) and then the Dino would chew on it. Afterwards, the dinosaur would spit out the food and urge the children to put in more.

Initial Prototyping
Functionality

Due to technical difficulties, our project did not perform as expected during the demo. We ran the toy many times to ensure that it would work by the day of the demo, however, this preemptive work could have been our very downfall.

Unfortunately, at the museum, we encountered a variety of electrical issues that impeded the performance of the project. We believe our power supply was broken or our Arduino was overloaded and that this caused our servos to freak out. Whenever we ran the Arduino through power, the servos behaved very strangely. This prevented the children from using our project.

However, many children still seemed every interested in the concept and really wanted to see it work. This showed us that the concept of our idea was engaging, and that even when they don’t work, dinosaurs are still eye catching.

While our user feedback was limited due to such an early failure, we could see that we still had a solid design to go forward with. Apart from fixing the glaring technical problems, our goal moving forward is still to improve off of our first iteration. We think it would be more engaging to add more complexity to the base code. Currently, until the Dino is fed, it is stationary, waiting for something to enter it’s mouth. Adding a slow yawning motion would be more enticing for the children to see it is alive and active. We are also considering a speaker to add noise into certain actions and potentially give the toy more personality.

The play by play moving forward really relies on how we can resolve our technical issues. Since it is uncertain why we encountered this issue, the amount of time it will take to solve it is highly variable. Randomly, while at least one power source is connected to power, the servos will start jittering and the machine becomes completely unresponsive. Unplugging both power sources and starting with plugging back in the shield board would often reset it but by the time the second child had shown up, the machine couldn’t do anything else. We will have to test the power sources, the shield and the Arduino.

Next, or even during problem resolution, we’ve decided to make a slightly larger Dino. This will include scaling the CAD and adding laser cut holes so they are a bit more precise than drilling by hand. The four bar linkage will need to be upgraded so it is more robust. Instead of using stray wires, we can use actual twine or aluminum wire or even a solid laser cut linkage so that the system is more sturdy.

If time permits, we will need to do some research into the speakers, playing around with them to find our desired frequencies. Before this, adding tweaks into the code to create more engaging behaviors will be a simple change to improve behavior. We have also decided to shift from our between state of decoration that is part minimalist and part covered to something that is fully covered and decorated.

Overall our challenges are manageable and our next steps for a further developed project are attainable. This time the Dinos fight extinction.

Code:

#include <Servo.h&gt;

const int SEN_PIN1 = A0;
const int SEN_PIN2 = A1;

const int MOUTH_SVO_PIN1 = 7;
const int MOUTH_SVO_PIN2 = 8;
const int LEFT_LEG_SVO_PIN = 4;
const int RGHT_LEG_SVO_PIN = 2;

Servo mouth_svo1, mouth_svo2, l_leg_svo, r_leg_svo;

const int SVO1_OPEN = 80;
const int SVO2_OPEN = 100;
const int SVO1_CLOSE = 130;
const int SVO2_CLOSE = 50;

const int SEN1_THRES = 650;
const int SEN2_THRES = 650;

long chew_t = 0;
long chew_start = 0;

void setup() {
  Serial.begin(9600);

  mouth_svo1.attach(MOUTH_SVO_PIN1);
  mouth_svo2.attach(MOUTH_SVO_PIN2);
  l_leg_svo.attach(LEFT_LEG_SVO_PIN);
  r_leg_svo.attach(RGHT_LEG_SVO_PIN);

  open_mouth();
  l_leg_svo.write(70);
  r_leg_svo.write(110);
}

long start_t = millis();
void loop() {
  long curr_t = millis();

  int sen1_val = analogRead(SEN_PIN1);
  int sen2_val = analogRead(SEN_PIN2);
//  lean_forward();

  if (sen1_val < SEN1_THRES || sen2_val < SEN2_THRES) {
    if (!chew_t) {
      chew_t = millis();
      chew_start = chew_t;
      close_mouth();
    }
  }

  if (chew_t) {
    chew(curr_t);
    chew_t = millis();
    if (chew_t - chew_start &gt; 5000) {
      chew_t = 0;
      open_mouth();
      delay(500);
      lean_forward();
    }
  }

  Serial.print(chew_t);
  Serial.print("\t");
  Serial.print("");
  Serial.print("\t");
  Serial.print(sen1_val);
  Serial.print("\t");
  Serial.println(sen2_val);
}

void chew(long curr_t) {
  int a = 5;
  mouth_svo2.write(a*sinf((float)curr_t/150) + 20);
  mouth_svo1.write(-a*sinf((float)curr_t/150) + (180-20));
}

void open_mouth() {
  mouth_svo1.write(SVO1_OPEN);
  mouth_svo2.write(SVO2_OPEN);
}

void close_mouth() {
  mouth_svo1.write(SVO1_CLOSE);
  mouth_svo2.write(SVO2_CLOSE);
}

void lean_forward() {
  l_leg_svo.write(120);
  r_leg_svo.write(60);
  delay(5000);
  l_leg_svo.write(70);
  r_leg_svo.write(110);
  delay(2000);
}
]]>
https://courses.ideate.cmu.edu/16-223/f2019/work/2019/11/06/dining-dino-intermediate-progress-report-edward-and-quincy/feed/ 0