We created a flapping bird toy that would move and chirp depending on how close you got to it. We encountered a couple issues with the performance of our device. The distance sensor stopped working and while sometimes being within the range of it would trigger the flapping and chirping, to the children, it wasn’t clear that a movement event was the cause of the bird’s reaction. Throughout the two hours we demoed, the hinges started falling off and the motor inside of the base came off. However, we had a previous version of our design without the electronics and we found the children were much more interested in that version.

Mechanical Design

The moving wings and beak are designed to be operated by pulleys that are strung throughout the hollow body. The beak uses a small spring to keep it in the open position, while the string is able to pull it closed.

The yellow string controls the beak, while the green strings control the wings. In the box, two servos are able to activate them.

Bird design in action, originally, weights were needed because the hinges were tight.

After it was working, we decorated it to really stand out.

Software Design

/*
 * created by Rui Santos, https://randomnerdtutorials.com
 * 
 * Complete Guide for Ultrasonic Sensor HC-SR04
 *
    Ultrasonic sensor Pins:
        VCC: +5VDC
        Trig : Trigger (INPUT) - Pin11
        Echo: Echo (OUTPUT) - Pin 12
        GND: GND
 */
#include <Servo.h&gt;
#define SPEAKER 3
#define SERIAL  
Servo bird;
int trigPin = 11;    // Trigger
int echoPin = 12;    // Echo
long duration, cm, inches;
long next_output_time_motor = 0;
long next_output_time_sound = 0;
int motor_state = LOW;

void setup() {
  //Serial Port begin
  Serial.begin (9600);
  bird.attach(4);
  //Define inputs and outputs
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  #ifdef SERIAL
   Serial.begin(9600);
#endif
  pinMode(SPEAKER,OUTPUT); 
}
 
void loop() {
  long now = micros();
  // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  digitalWrite(trigPin, LOW);
  delayMicroseconds(5);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
 
  // Read the signal from the sensor: a HIGH pulse whose
  // duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
 
  // Convert the time into a distance
  cm = (duration/2) / 29.1;     // Divide by 29.1 or multiply by 0.0343
  inches = (duration/2) / 74;   // Divide by 74 or multiply by 0.0135
  
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  
  if (now &gt;next_output_time_motor &amp;&amp; inches < 13 &amp;&amp; motor_state){
    bird.write(0);
    next_output_time_motor = now + (1300-((13-inches))*100);
    motor_state = !motor_state;
  }
  if (now &gt; next_output_time_motor &amp;&amp; inches < 13 &amp;&amp; !motor_state){
    bird.write(180);
    next_output_time_motor = now + (1300-((13-inches))*100);
    motor_state = !motor_state;
    }
  if (now &gt; next_output_time_sound &amp;&amp; inches < 13){
    int chirpnum = random(0,4);
    Serial.println(chirpnum);
    if (chirpnum == 0){
      chirp();
    }
    if (chirpnum == 1){
      chirp2();  
    }
    if (chirpnum == 2){
      chirp3();  
    }
    if (chirpnum == 3){
      chirp4();
    }
    next_output_time_sound = now + 20;    
    }
    
}


void chirp() {  // Bird chirp
  for(uint8_t i=190; i&gt;170; i-=2)
     playTone(i,9);
     
}

void chirp2() {  // Bird chirp
  for(uint8_t i=250; i&gt;220; i-=1)
     playTone(i,9);
     
}

void chirp3() {  // Bird chirp
  for(uint8_t i=180; i<200; i++ )
     playTone(i,9);
     
}

void chirp4() {  // Bird chirp
  for(uint8_t i=250; i&gt;150; i--)
     playTone(i,9);
  for(uint8_t i=180; i<250; i++)
     playTone(i,9);
     
}
// play tone on a piezo speaker: tone shorter values produce higher frequencies
//  which is opposite beep() but avoids some math delay - similar to code by Erin Robotgrrl
 
void playTone(uint16_t tone1, uint16_t duration2) {
  if(tone1 < 50 || tone1 &gt; 15000) return;  // these do not play on a piezo
  for (long i = 0; i < duration2 * 1000L; i += tone1 * 2) {
     digitalWrite(SPEAKER, HIGH);
     delayMicroseconds(tone1);
     digitalWrite(SPEAKER, LOW);
     delayMicroseconds(tone1);
  }     
}