OM-NOM-Garbagecan


OM NOM is kinda scary and encourages waste. When you feed him he RAWRZ angrily, then he’ll aggressively begs for food, though he appreciates your actions after you feed him. If you don’t feed him for 12 hours he’ll get super P/O’d and let you know it.

OM-NOM uses a photocell to know when his mouth is open, the LCD screen tells you his emotional state using text and image, and a little speaker lets him emote vocally.



He has 4 states.
+Opening Roar – When he first opens his mouth he kind of RAWRZ.
+Begging – If you leave him open he keeps begging for food / garbage.
+Happy – Once he’s been fed, he’ll emote happily and make an nom nom nom noise.
+Hungry – If you don’t feed him for more than 12 hours he’ll repeatedly make an angry noise every 10 minutes until you feed him / throw something away.




He’s constructed with a cleaned out delivery food container with all the various electronics held in place with duct tape, thumb tacks, and brass hangers. Pretty ghetto, but it works!

CODE!

#include "ST7565.h"
#include "face_bitmaps.h"
#include "pitches.h"   

int photoPin=0;
int speaker=13;
int reading;  //holds the current photo reading
unsigned long time;
unsigned long previousTime = 0;   
long interval = 43200000; //12 hours

boolean open = false;
boolean stillOpen = false;

// the LCD backlight is connected up to a pin so you can turn it on & off
#define BACKLIGHT_LED 10

// pin 9 - Serial data out (SID)
// pin 8 - Serial clock out (SCLK)
// pin 7 - Data/Command select (RS or A0)
// pin 6 - LCD reset (RST)
// pin 5 - LCD chip select (CS)
ST7565 glcd(9, 8, 7, 6, 5);

void setup()   {                
  Serial.begin(9600);
  Serial.print(freeRam());
  // turn on backlight
  pinMode(BACKLIGHT_LED, OUTPUT);
  digitalWrite(BACKLIGHT_LED, HIGH);

  glcd.st7565_init();
  glcd.st7565_command(CMD_DISPLAY_OFF);
  glcd.st7565_command(CMD_SET_ALLPTS_NORMAL);
  glcd.st7565_set_brightness(0x18);

  glcd.display(); // show splashscreen

  glcd.clear();
  pinMode(11, OUTPUT);  
}

void loop()                     
{
  glcd.clear();
  reading=analogRead(photoPin);
  time = millis();

  if(reading > 200){
    open = true; 
    // I reset interval incase it was adjusted
    // while OmOm was hungry.
    interval = 43200000; 
    previousTime = time;
    glcd.st7565_command(CMD_DISPLAY_ON);
  }
  else
    open = false;

  if(open == true && stillOpen == false) {
    openRoar();
    stillOpen = true;
    previousTime = time;
  }

  if(stillOpen == true) {
    begging();
    previousTime = time;
  }

  if(open == false && stillOpen == true) {
    happy();
    stillOpen = false;
    previousTime = time;
    glcd.st7565_command(CMD_DISPLAY_OFF);
  }

  if(time - previousTime > interval) {
    glcd.st7565_command(CMD_DISPLAY_ON);
    hunger();
    interval += 600000;
    glcd.st7565_command(CMD_DISPLAY_OFF);
  }


  Serial.println(analogRead(photoPin));
}

void hunger() { 
  int hungry[] = {
    NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4, NOTE_FS4, NOTE_A4,                                                               };
  int hungryDurations[] = {
    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16                                                              };
  boolean on = false;

  // draw a string at location
  for(int i=0; i<20; i++) {

    if (analogRead(photoPin) > 200){
      i = 20;
    }

    glcd.drawstring(22, 3, "!!I'M HUNGRY!!"); 
    glcd.display();
    int hungryDuration = 1000/hungryDurations[i];
    tone(speaker, hungry[i], hungryDuration);
    if (on == true) {
      digitalWrite(11, HIGH);
      on = false;
    }
    else {
      digitalWrite(11, LOW);
      on = true;
    }
    delay(hungryDuration);
  }
  noTone(speaker);

  for(int i=0; i<10; i++) {

    if (analogRead(photoPin) > 200){
      i = 10;
    }
    int hungryDuration = 2500/hungryDurations[i];
    tone(speaker, hungry[i], hungryDuration);
    if (on == true) {
      digitalWrite(11, HIGH);
      on = false;
    }
    else {
      digitalWrite(11, LOW);
      on = true;
    }
    delay(hungryDuration);
  }
  glcd.clear();
  noTone(speaker);
  digitalWrite(11, LOW);
}

void openRoar() {
  int lowVal = NOTE_C2;
  int highVal = NOTE_AS3;
  int val = lowVal;
  int incr = 10;

  // draw a string at location
  for(val; val<highVal; val+=incr) {

    if (analogRead(photoPin) < 200){
      val = highVal;
    }

    glcd.drawbitmap(0,0,roar_bmp,ROAR_WIDTH, ROAR_HEIGHT, BLACK);
    glcd.display();
    tone(speaker, val);
    digitalWrite(11, HIGH);
    delay(3);
  }
  glcd.clear();
  digitalWrite(11, LOW);
  incr = 5;

  // draw a bitmap roar
  if(analogRead(photoPin) > 200) {
    for(val; val>lowVal; val-=incr) {

      if (analogRead(photoPin) < 200){
        val = lowVal;
      }

      glcd.drawstring(30, 3, "!!RAWWWRZ!!");
      glcd.display();
      tone(speaker, val);
      digitalWrite(11, HIGH);
      delay(3);
    }
  }
  glcd.clear();
  digitalWrite(11, LOW);
}

void begging() {
  int omom[] = {
    NOTE_B2, NOTE_A2,0,NOTE_B2, NOTE_A2,0,NOTE_B2, NOTE_A2,0                      };
  int omomDurations[] = {
    16,16,2,16,16,2,16,16,2                      };
  boolean on = false;

  // draw a string at location
  for(int i=0; i<9; i++) {

    if (analogRead(photoPin) < 200){
      i = 9;
    }

    glcd.drawbitmap(0,0,happy_bmp,HAPPY_WIDTH, HAPPY_HEIGHT, BLACK);
    glcd.display();
    int omomDuration = 1000/omomDurations[i];
    tone(speaker, omom[i], omomDuration);
    if (on == true) {
      digitalWrite(11, HIGH);
      on = false;
    }
    else {
      digitalWrite(11, LOW);
      on = true;
    }
    delay(omomDuration);
  }
  glcd.clear();
  noTone(speaker);
  digitalWrite(11, LOW);

  // draw a bitmap roar
  for(int i=0; i<9; i++) {

    if (analogRead(photoPin) < 200){
      i = 9;
    }

    glcd.drawstring(26, 3, "!!OM OM OM!!");
    glcd.display();
    int omomDuration = 500/omomDurations[i];
    tone(speaker, omom[i], omomDuration);
    if (on == true) {
      digitalWrite(11, HIGH);
      on = false;
    }
    else {
      digitalWrite(11, LOW);
      on = true;
    }
    delay(omomDuration);
  }
  glcd.clear();
  noTone(speaker);
  digitalWrite(11, LOW);
}

void happy() {

  glcd.drawstring(15, 3, "!!MMMM NOM NOM!!");
  glcd.display();

  tone(speaker, NOTE_F4);
  digitalWrite(11, HIGH);
  delay(1000/16);
  tone(speaker, NOTE_G4);
  delay(1000/16);
  tone(speaker, NOTE_C5);
  delay(500);
  tone(speaker, NOTE_B4);
  delay(1000/16);
  tone(speaker, NOTE_AS4);
  delay(1000/16);
  digitalWrite(11, LOW);

  for(int i=0; i<2; i++) {
    digitalWrite(11, HIGH);
    tone(speaker, NOTE_E4);
    delay(1000/16);
    tone(speaker, NOTE_D4);
    delay(1000/16);
    tone(speaker, NOTE_CS4);
    delay(1000/16);
    digitalWrite(11, LOW);
    noTone(speaker);
    delay(500);
  }
  digitalWrite(11, LOW);

  if(analogRead(photoPin) < 200) {
    tone(speaker, NOTE_F4);
    digitalWrite(11, HIGH);
    delay(1000/16);
    tone(speaker, NOTE_G4);
    delay(1000/16);
    tone(speaker, NOTE_C5);
    delay(500);
    tone(speaker, NOTE_B4);
    delay(1000/16);
    tone(speaker, NOTE_AS4);
    delay(1000/16);
    digitalWrite(11, LOW);

    for(int i=0; i<2; i++) {
      digitalWrite(11, HIGH);
      tone(speaker, NOTE_E4);
      delay(1000/16);
      tone(speaker, NOTE_D4);
      delay(1000/16);
      tone(speaker, NOTE_CS4);
      delay(1000/16);
      digitalWrite(11, LOW);
      noTone(speaker);
      delay(500);
    }
  }
  glcd.clear();
  digitalWrite(11, LOW);
}

int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
}