Completely Bodiless Nick

For my stupid pet trick, I was planning on creating a head that “lives” in a box, which can be opened in multiple ways, to arrive at different questions the head would ask each time. However, using servos for even the rotating display of the question proved to be difficult (due to the weight of the component), thus I changed my project and turned it into an interactive and friendly head, Completely Bodiless Nick. Different inputs, for instance a “high five”, make him react in different ways.

Nick has 2 RGB lights as eyes, covered with ping-pong balls, four yellow lights at its top (might be interpreted as hair), a red LED on the “control pad” in front, a two-sided rotating component as a mouth (moved by a micro servo), and a piezo buzzer connected directly to the RedBoard behind him. Beside these outputs, the inputs I included are: 1) a light sensor, 2) a potentiometer and 3) a push button.

The original idea behind the light sensor would have been to make it the spot where the “visitor” coming to the box could place a gift for the head living inside, thus triggering a kind mood. Since the idea of the box was dropped, this concept had to be changed, so the light sensor was used to make Nick react to “high fives”. When the hand of the user blocks the light from the sensor, a threshold value is reached, below which Nick’s eyes turn green and the yellow lights turn on, while a cheerful (kind of, except for the annoying-sound factor) melody is played, signaling that Nick likes receiving high-fives.

The potentiometer was to be used for allowing the user to choose an answer from 3 options, after the box is opened and the head asks the question. Without the box though, it would not have been possible to ask more than one question (as the display component had only two sides, and one of them had to be neutral, since it would always be shown), so I altered the function of the potentiometer as well. The reason I kept all my planned inputs is that they were already wired up anyways so the only thing I had to do was come up with a different story behind them. Thus, I decided to use the potentiometer as a simple light and sound control, and for letting Nick know if you happen to have birthday. Below a certain value read from the potentiometer (a small range close to the minimum), the eyes turn blue, in another small interval around the middle of the range of possible values, the eyes turn green, and above a value close to the maximum, all lights turn on and “Happy birthday” is played.

Finally, a “don’t use” label was placed beside the push button on the control pad. Obviously, the users will want to see what the button does, why they are not allowed to use it, so it is expected that they would press it. As the button is pushed, Nick’s eyes go red, the warning light turns on, a warning signal is played by the piezo, and Nick reminds the user: “I said don’t” (this is achieved by the rotation of his mouth component, turning from the smiley side to the text side, suggesting speech).

Most of the difficulties I had to face were majorly physical and related to the servo. Beside the fact that the servo could hardly support the weight of the planned components, attaching them to the servo was also problematic. Moreover, as the positions of the servo are not perfectly precise, calibrating it to rotate just as much as needed was also a challange. Apart from the servo, the RGB lights, to my surprise (as I have already used them but have not experienced difficulty with them before) were also hard to use, on the one hand because the pins had to be glued to the board far apart so that they would definitely not touch, and on the other hand because when trying to mix colors, they would not create blends but one would overwrite the other (eg I couldn’t make purple; this was something that has not been a problem so far and I don’t exactly understand why this occurred).

The code of my project’s servo and sound parts is largely based on the relevant libraries of the Arduino. To play happy birthday, I altered the code in Melody.h as shown here.

Documentation: https://drive.google.com/a/nyu.edu/folderview?id=0BwGOKPbccFXuTUNyX1VVRlhkUms&usp=sharing

Code:

#include <Servo.h>
#include "pitches.h"


Servo qaservo;

//inputs:
int bell = 2;
int gift = A1;
int answer = A2;

//outputs:
int sound = 3;
int lights = 4;
int warninglights = 7;

int eyeRED = 9;
int eyeBLUE = 11;
int eyeGREEN = 10;

//outputs-->servo:
int qa = 5;


int on = HIGH;
int off = LOW;


void setup() {
  // put your setup code here, to run once:

Serial.begin(9600);
qaservo.attach(qa);
qaservo.write(160);


pinMode(bell, INPUT);

pinMode(eyeRED, OUTPUT);
pinMode(eyeBLUE, OUTPUT);
pinMode(eyeGREEN, OUTPUT);
pinMode(lights, OUTPUT);
pinMode(sound, OUTPUT);
pinMode(warninglights, OUTPUT);

digitalWrite(lights, off);
digitalWrite(warninglights, off);
digitalWrite(sound, off);
analogWrite(eyeRED, 0);
analogWrite(eyeBLUE, 0);
analogWrite(eyeGREEN, 0);
}


void loop() {
  // put your main code here, to run repeatedly:

int val = analogRead(gift);
int ans = analogRead(answer);
Serial.print(ans);
Serial.println(val);

if (digitalRead(bell) == on && analogRead(gift) > 400)
{
  warning(); 
  question1(); 
  scenarioRude();
}

else if (analogRead(gift) < 400 && digitalRead(bell) == off)
{
  bellsound();
  question2();
  scenarioKind();
}


else
{
digitalWrite(lights, off);
digitalWrite(warninglights, off);
digitalWrite(sound, off);
analogWrite(eyeRED, 0);
analogWrite(eyeBLUE, 0);
analogWrite(eyeGREEN, 0);
}


}



void question1()
{
  qaservo.write(35);
}

void question2()
{
 qaservo.write(140);  
}


void scenarioRude()
{
  delay(3000);
  digitalWrite(eyeRED, on);
  digitalWrite(warninglights, on);
  digitalWrite(lights, off);

  if (analogRead(answer) < 400)
  {
    func1();
  }

  else if ( 400 <= analogRead(answer))
  {
    grump();
  }
}

void scenarioKind()
{
 delay(3000);
 digitalWrite(eyeBLUE, on);
 digitalWrite(warninglights, off);
 digitalWrite(lights, on);
 
 if (analogRead(answer) < 400)
  {
    yeyy();
  }

  else if ( 400 <= analogRead(answer) && analogRead(answer) < 530)
  {
    func1();
  }

  else 
  {
    grump();
  }
 
 
}

void yeyy()
{
 digitalWrite(lights, on);
 int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};
for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(sound, melody[thisNote], noteDuration);
    digitalWrite(lights, on);
    digitalWrite(eyeBLUE, off);
    digitalWrite(eyeGREEN, on);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    digitalWrite(lights, off);
    digitalWrite (eyeBLUE, on);
    digitalWrite(eyeGREEN, off);
    // stop the tone playing:
    noTone(8);
}
}

void func1()
{
 digitalWrite(lights, on);
 digitalWrite(eyeBLUE, off);
 delay(350);
 digitalWrite(eyeBLUE, on);
 digitalWrite(lights, off);
 delay(350); 
 digitalWrite(lights, on);
 digitalWrite(eyeBLUE, off);
 delay(300);
 digitalWrite(eyeBLUE, on);
 digitalWrite(lights, off);
 delay(300); 
 digitalWrite(lights, on);
 digitalWrite(eyeBLUE, off);
 delay(200);
 digitalWrite(eyeBLUE, on);
 digitalWrite(lights, off);
 delay(200); digitalWrite(lights, on);
 digitalWrite(eyeBLUE, off);
 delay(100);
 digitalWrite(eyeBLUE, on);
 digitalWrite(lights, off);
 delay(100); 
}

void grump()
{
  warning();
  digitalWrite(eyeRED, on);
  delay(100);
  digitalWrite(eyeRED, off);
}


void warning()
{
    digitalWrite(warninglights, on);
    tone(sound, 440);
    delay(100);

    digitalWrite(warninglights, off);
    noTone(sound);
    delay(100);
    
    tone(sound, 500);
    digitalWrite(warninglights, on);
    delay(100);
 
    digitalWrite(warninglights, off);
    noTone(sound);
    delay(100);
  
}

void bellsound()
{
  int melody[] ={NOTE_A4, NOTE_B4, 0, NOTE_A4, NOTE_B4};
int noteDurations[] = {16,16,8,16,16};

  for (int thisNote = 0; thisNote < 4; thisNote++) {
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(sound, melody[thisNote], noteDuration);
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(sound);
  }

}

 

Leave a Reply