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; }
makingtoys 8:43 pm on February 17, 2011 Permalink |
Lee, great project. But please post your code in the post in the ‘read more’ section.
makingtoys 3:30 am on February 18, 2011 Permalink |
this project is awesome. i love this. this is “viral product” material.
makingtoys 3:45 am on February 18, 2011 Permalink |
great videos, great documentation.
Lee 3:27 pm on February 18, 2011 Permalink |
Thanks I fully intend to try and develop this more. I’d be interested to try and figure out how to actually sell it this summer.