Jason Kim Midterm: Stupid Pumpkin

1) Project Name: Stupid Pumpkin

The concept of the Stupid Pumpkin is relatively straightforward. It’s a pumpkin that looks stupid and a pumpkin that people would want to hit. Using two tilt sensors, I could detect if the pumpkin was hit from the left or from the right. If hit from the right side, the servo motor turns in a clockwise direction (counter clockwise if hit from left) and the Stupid Pumpkin makes a sad face and starts to cry. The LEDs representing the mouth of the pumpkin are controlled by a shift register. The eyes of the pumpkin are RGB LEDs that change color every time the pumpkin is hit. Near the nose (fading superbright blue LED) of the pumpkin is also a photocell that detects if the pumpkin’s nose is covered or if the lights are turned off. If the nose is covered or lights are turned off, the Stupid Pumpkin starts to cry as it is lonely and frightened. The inside of the pumpkin are all wires and circuit boards and uses no bread boards. Circuit boards are screwed on the inside wall of the pumpkin. The Arduino is powered by a 9V battery pack.

2) A photo of the electronics and final project

3) A short video demonstrating it

4) The Arduino code

<pre>//Midterm Pumpkin Jason Kim

//Photocell
int photocellPin = A3;
int photocellReading;

//Servo Motor
#include <Servo.h>
Servo myServo;
int noTurn = 90;

//Shift Register 75HC595
int SER_Pin = 11;   //pin 14 on the 75HC595 bluewire
int RCLK_Pin = 8;  //pin 12 on the 75HC595 greenwire
int SRCLK_Pin = 12; //pin 11 on the 75HC595 yellowwire
#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8

//Pumpkin eyes
const int redPin = A0;
const int greenPin = A1;
const int bluePin = A2;
const boolean invert = true;

int color = 0;
int R, G ,B;

//Pumpkin tear eyes
int eyePin[] = {
  6,3};

int eyePin2[] = {
  9,10};

int brightness2 = 0;
int brightness3 = 0;

//Pumpkin nose
int brightness = 0;
int fadeAmount = 5;
int nosePin = 5;

//Pumpkin hit (tilt sensor)
int tiltPin[] = {
  7,4};
int tiltState = 0;
int tiltState2 = 0;

//test led
int testPin = 13;

boolean registers[numOfRegisterPins];

void setup(){
  Serial.begin(9600);
  myServo.attach(2);
  myServo.write(noTurn);
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  pinMode(nosePin, OUTPUT);
  for(int i = 0; i<2; i++){
    pinMode(tiltPin[i], INPUT);
  }
  for(int j = 0; j<2; j++){
    pinMode(eyePin[j],OUTPUT);
  }
  for(int k = 0; k<2; k++){
    pinMode(eyePin2[k],OUTPUT);
  }
  clearRegisters();
  writeRegisters();
}       

//set all register pins to LOW
void clearRegisters(){
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    registers[i] = LOW;
  }
}
void writeRegisters(){
  digitalWrite(RCLK_Pin, LOW);
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(SRCLK_Pin, LOW);
    int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

void setRegisterPin(int index, int value){
  registers[index] = value;
}

void loop(){
  tiltState = digitalRead(tiltPin[0]);
  tiltState2 = digitalRead(tiltPin[1]);
  photocellReading = analogRead(photocellPin);
  photocellReading = 1023 - photocellReading;
  if (photocellReading > 500 && photocellReading < 600){
    myTear();
  }
  Serial.print("Photocell reading = ");
  Serial.println(photocellReading);
  //Pumpkin Eyes
  myEye();
  //Pumpkin Nose
  myNose();
  //Pumpkin Hit
  myHit();
  //Pumpkin Mouth
  myHappy();
  writeRegisters();
  if(tiltState == HIGH){
    myServo.write(111);
    mySad();
    myEyeHit();
    writeRegisters();
    myTear();
    delay(500);
    myServo.write(noTurn);
  }
  if(tiltState2 == HIGH){
    myServo.write(71);
    mySad();
    myEyeHit();
    writeRegisters();
    myTear();
    delay(500);
    myServo.write(noTurn);
  }
}
void myHappy(){
  setRegisterPin(0, HIGH);
  setRegisterPin(3, HIGH);
  setRegisterPin(5, HIGH);
  setRegisterPin(6, HIGH);
  setRegisterPin(1, LOW);
  setRegisterPin(2, LOW);
  setRegisterPin(4, LOW);
  setRegisterPin(7, LOW);
}
void mySad(){
  setRegisterPin(1, HIGH);
  setRegisterPin(2, HIGH);
  setRegisterPin(4, HIGH);
  setRegisterPin(7, HIGH);
  setRegisterPin(0, LOW);
  setRegisterPin(3, LOW);
  setRegisterPin(5, LOW);
  setRegisterPin(6, LOW);
}
void myNose(){
  analogWrite(nosePin, brightness);
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255){
    fadeAmount = -fadeAmount;
  }
  delay(30);
}
void myHit(){
  if(tiltState == HIGH){
    digitalWrite(testPin, HIGH);
  }
  else if(tiltState2 == HIGH){
    digitalWrite(testPin, HIGH);
  }
  else{
    digitalWrite(testPin, LOW);
  }
}
void myTear(){
  for(int i =0; i < 2; i++){
    //one LED fade
    for(int brightness2 = 0; brightness2 <= 255; brightness2 +=5){
      analogWrite(eyePin[i], brightness2);
      //      analogWrite(eyePin2[i],brightness2);
      delay(10);
    }
    for(int brightness2 = 255; brightness2 >= 0; brightness2 -=5){
      analogWrite(eyePin[i],brightness2);
      //      analogWrite(eyePin2[i],brightness2);
      delay(10);
    }
  }
}
void myLeftTear(){
  for(int i = 0; i < 2; i++){
    //one LED fade
    for(int brightness3 = 0; brightness3 <= 255; brightness3 +=5){
      //      analogWrite(eyePin[i],brightness2);
      analogWrite(eyePin2[i],brightness3);
      delay(10);
    }
    for(int brightness3 = 255; brightness3 >= 0; brightness3 -=5){
      //      analogWrite(eyePin[i],brightness2);
      analogWrite(eyePin2[i],brightness3);
      delay(10);
    }
  }
}
void myEye(){
  int brightnessEye = 255;
  hueToRGB(color, brightnessEye);
  analogWrite(redPin, R);
  analogWrite(greenPin, G);
  analogWrite(bluePin, B);
  if(color > 255){
    color = 0;
  }
  delay(10);
}
void myEyeHit(){
  int brightness = 100;
  hueToRGB(color, brightness);
  analogWrite(redPin, R);
  analogWrite(greenPin, G);
  analogWrite(bluePin, B);
  color+=60;
  if(color > 255){
    color = 0;
  }
  delay(10);
}
void hueToRGB( int hue, int brightness){
  unsigned int scaledHue = (hue * 6);
  unsigned int segment = scaledHue / 256; //segment 0 to 5 round the color wheel
  unsigned int segmentOffset = scaledHue - (segment * 256); //position within segment
  unsigned int complement = 0;
  unsigned int prev = (brightness * ( 255 - segmentOffset)) / 256;
  unsigned int next = (brightness * segmentOffset) / 256;
  if(invert){
    brightness = 255-brightness;
    complement = 255;
    prev = 255-prev;
    next = 255-next;
  }
  switch(segment ){
  case 0: //red
    R = brightness;
    G = next;
    B = complement;
    break;
  case 1: //yellow
    R = prev;
    G = brightness;
    B = complement;
    break;
  case 2: //green
    R = complement;
    G = brightness;
    B = next;
    break;
  case 3: //cyan
    R = complement;
    G = prev;
    B = brightness;
    break;
  case 4: //blue
    R = next;
    G = complement;
    B = brightness;
    break;
  case 5: //magenta
  default:
    R = brightness;
    G = complement;
    B = prev;
    break;
  }
}