Monsters Inc.
Scare Factory
Child's Room and Scarer Game
By: Lauren Antilla and Rabea Baroudi
Project Description
Remote Site 2 is the Child’s Room and Scarer Game for our Monster’s Inc. Scare Factory prototype.This is the part of the system where the user moves their monster through the enclosure to scare the child and have the child output a scream for the other remote site to collect with their Scream Canister. In order to replicate the process in the movie, there is a door at the front that has a light that turns on when the door is activated and ready to be entered by the monster. It is actually a game, where the user tries to get a higher scare power to output a better scream. This is accomplished by first reaching the area where the motion sensor is activated and the monster is thus close enough to scare them, and then increasing the score by pressing the button as many times as possible once gameplay begins. A scream is then chosen and released and a picture of the scarer is taken for the leadership board.
​
​
System Diagram
Breadboard Layout
Arduino 1: Sensors Connected to the Enclosure
Arduino 2: Audio Component
This site utilizes three Arduinos to connect all of the appropriate sensors and components. The first Arduino, seen in Figure 1, contains a majority of our sensors and connects to the overall enclosure. It uses pieces such as a motion sensor, LED, buttons, and more to simulate a child’s room in Monster’s Inc. and to then have the selected character “scare” the child through the game we implemented. The next Arduino, in Figure 2, primarily deals with the MP3 component that outputs the scream so that Remote Site 1 could collect data about the scare. The final Arduino, which is displayed in Figure 3, is for the TTL Serial JPEG Camera we are using to take a picture of the monster at the time of the scare.
Arduino 3: Camera Module
Software
We ended up with four different files for our code: three Arduino and one in Python. These files can be seen at the end of this page. Overall, we separated the code based on the hardware, i.e. the MP3 player couldn't fit with most of the other sensors so it had its own Arduino and separate code. The general structure of the code (for everything but the camera) involves sending and receiving XBee messages, which was typically at the end of the loop. The code for Arduino 2 primarily involved setting up the music player and then responding to the case for the music to play, and so the module was actually activated in one of the XBee cases.
​
The code for Arduino 1 is structured so that it tests the states of the various sensors as it goes through the loop. There are many booleans to see if an if statement can be entered as there are some situations where the state of a sensor changing doesn't affect anything. For example, the motion sensor may technically be able to detect motion before the character enters the game, but because of the different conditions, the code responding to motion being detected will not actually do anything until certain factors are true.
​
There are two files for the camera code, as we needed Python to save the file to a folder on the desktop, which later allowed Processing to grab the image from the folder. The Arduino code takes the picture, saves it to the SD card, and then writes it over the Serial Port, while the Python code creates a JPG file from the resulting data it receives.
Project Code
Arduino 1: Sensors Connected to the Enclosure
// Attribution: XBee Code from HCDE 439 Lecture
​
#include <SoftwareSerial.h>
#include <Button.h>
#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <Servo.h>
​
Servo servo;
Adafruit_LiquidCrystal lcd(0);
const String myNodeName = "Child's Room";
String scarers[] = {"SULLIVAN", "RANDALL", "RANFT", "LUCKEY", "RIVERA", "PETERSON", "JONES", "SANDERSON", "PLESUSKI", "SCHIMDT", "MIKE"};
String scarer = "";
const byte TAB_CHAR = 0x09;
const byte NEWLINE_CHAR = 0x0A;
// game play
Button btn1Game(7);
Button btn2Game(6);
Button btnGame();
int timer = 15;
long currMillis = 0;
int btnCount = 0;
int currNum = 0;
boolean start = false;
boolean printed = false;
boolean game = false;
boolean setTimer = false;
boolean done = false;
boolean btnsActive = false;
int action = 0;
boolean lightOn = false;
const int motionPin = 8;
const int ledDoor = 11;
int pirState = 0;
boolean motionRound = false;
const int laser = 10;
boolean btn1Active = false;
boolean btn2Active = false;
int actionGame = 0;
boolean exitDoor = false;
String msg = "";
int code = 0;
const int MAX_FIELDS = 4;
// initialize the serial port for the xBee with whatever pins are used
SoftwareSerial xBee(2, 3); // (TX, RX) : pins on XBee adapter
void setup() {
lcd.begin(16, 2);
Serial.begin(38400);
Serial.println("\n\nxBeeSendReceiveMsg");
pinMode(motionPin, INPUT);
pinMode(laser, OUTPUT);
pinMode(ledDoor, OUTPUT);
// initialize and set the data rate for the SoftwareSerial port -- to
// send/receive messages via the xBee
xBee.begin(38400);
servo.attach(9);
servo.write(180);
}
​
void loop() {
// have received message that door is ready but haven't pressed
// btn
if(!btnsActive && lightOn) { //&& lightOn
int action1 = btn1Game.checkButtonAction();
int action2 = btn2Game.checkButtonAction();
if(action1 == Button::PRESSED) { // character 1 chosen
btnsActive = true;
btn1Active = true;
doorOpen();
} else if(action2 == Button::PRESSED) { // character 2 chosen
btnsActive = true;
btn2Active = true;
doorOpen();
}
}
if(btn1Active) {
actionGame = btn1Game.checkButtonAction();
} else {
actionGame = btn2Game.checkButtonAction();
}
// game over
if(exitDoor && actionGame == Button::PRESSED) {
lcd.clear();
servo.write(180);
digitalWrite(ledDoor, LOW);
} else if (actionGame == Button::PRESSED && !motionRound &&
btnsActive) {
code = 2319; // contamination
msg = myNodeName + "\t" + code + "\n";
xBee.print(msg);
Serial.println(msg);
contamination();
}
// check motion sensor
pirState = digitalRead(motionPin);
if(pirState == HIGH && !motionRound && btnsActive) {
motionRound = true;
int scarePower = gamePlay();
endRound();
if(scarePower == 0) {
code = 2319;
contamination();
} else {
code = 2100; // scarepower score found, send to mp3
}
msg = myNodeName + "\t" + code + "\t" + scarePower + "\n";
Serial.println(scarePower);
Serial.println(msg);
xBee.print(msg);
}
// check to see if any complete incoming messages are ready
String msg = checkMessageReceived();
if (msg.length() > 0) {
{
// this is just for logging the messages; or for debugging
Serial.println(msg);
}
String msgFields[MAX_FIELDS];
for (int i = 0; i < MAX_FIELDS; i++) {
msgFields[i] = "";
}
// initialize temporary variables used to process each message
int fieldsFound = 0;
String buf = "";
for (int i = 0; i < msg.length(); i++) {
if (((msg.charAt(i) == TAB_CHAR) ||
(msg.charAt(i) == NEWLINE_CHAR)) &&
(fieldsFound < MAX_FIELDS)) {
msgFields[fieldsFound] = buf;
buf = "";
fieldsFound++;
}
else {
buf += msg.charAt(i);
}
}
Serial.print("found fields = ");
Serial.println(fieldsFound);
for (int i = 0; i < fieldsFound; i++) {
Serial.println(msgFields[i]);
}
int aNumber = msgFields[1].toInt();
int scarerIndex = msgFields[2].toInt();
Serial.print("my second field contained the number = ");
Serial.println(aNumber);
switch (aNumber) {
// scarer name
case 2222:
Serial.println("Getting something");
break;
case 5555: // employee name
scarer = scarers[scarerIndex];
lcd.clear();
lcd.print("Press button to");
lcd.setCursor(0, 1);
lcd.print("enter, " + scarer);
Serial.println(scarer);
break;
// all clear after contamination
case 9999: //ending round after contamination
lcd.clear();
Serial.println("All clear");
digitalWrite(laser, LOW);
digitalWrite(ledDoor, LOW);
scarer = "";
motionRound = false;
lightOn = false;
btnsActive = false;
btn1Active = false;
btn2Active = false;
btnCount = 0;
start = false;
printed = false;
game = false;
setTimer = false;
done = false;
motionRound = false;
break;
case 1112: // light turns on
lightOn = true;
Serial.println("Light On");
digitalWrite(ledDoor, HIGH);
break;
case 5678:
Serial.println("Got it");
break;
default:
// if nothing else matches, do the default
Serial.println("code unknown");
break;
}
}
}
String checkMessageReceived () {
static String msgBuffer = ""; // buffer to collect incoming message:
// static instead of global !
String returnMsg = ""; // the result to return to the caller
if (xBee.available()) {
// there is at least one character in the input queue of the XBee,
// so fetch it. to prevent blocking the main loop, only one byte
// is fetched on each call. add it to the nsg buffer accumulating the
byte ch = xBee.read();
msgBuffer += char(ch);
if (ch == NEWLINE_CHAR) {
returnMsg = msgBuffer;
msgBuffer = "";
}
else {
}
}
else {
}
return returnMsg;
}
​
int gamePlay() {
while(!done) {
if(btn1Active) {
actionGame = btn1Game.checkButtonAction();
} else {
actionGame = btn2Game.checkButtonAction();
}
if(!start && !printed) {
printed = true;
lcd.clear();
lcd.print("Press button");
lcd.setCursor(0, 1);
lcd.print("to play");
} else if(!start) {
if(actionGame == Button::PRESSED) {
start = true;
lcd.clear();
lcd.print("Repeatedly press");
lcd.setCursor(0, 1);
lcd.print("to improve scare");
game = true;
delay(3000);
currMillis = millis();
}
} else {
if(game) {
int tot = millis() - currMillis;
tot = tot / 1000;
if(!setTimer) {
lcd.clear();
setTimer = !setTimer;
lcd.print("Time left:");
lcd.setCursor(13, 1);
lcd.print("sec");
}
int num = timer - tot;
if(actionGame == Button::PRESSED) {
btnCount++;
}
if(tot < timer && num != currNum) {
currNum = num;
lcd.setCursor(10, 1);
if(num < 10) {
lcd.print(" ");
}
lcd.print(num);
} else if(tot == timer) {
lcd.clear();
lcd.print("Round over...");
lcd.setCursor(0, 1);
lcd.print("Scare Power: ");
lcd.setCursor(13, 1);
lcd.print(btnCount);
game = false;
done = true;
return btnCount;
}
}
}
}
}
​
void doorOpen() {
lcd.clear();
lcd.print("Door opening");
servo.write(90);
delay(5000);
servo.write(180);
lcd.clear();
lcd.print("Child sleeping");
}
​
void endRound() {
exitDoor = true;
servo.write(90);
delay(3000);
lcd.clear();
lcd.print("Press button to");
lcd.setCursor(0, 1);
lcd.print("close door");
}
​
void contamination() {
digitalWrite(laser, HIGH);
lcd.clear();
lcd.print("Contamination!!!");
lcd.setCursor(0, 1);
lcd.print("Round over...");
ledFlash();
ledFlash();
ledFlash();
ledFlash();
digitalWrite(ledDoor, HIGH);
endRound();
}
​
void ledFlash() {
digitalWrite(ledDoor, LOW);
delay(500);
digitalWrite(ledDoor, HIGH);
delay(500);
}
Arduino 2: Audio Component
// Attribution: XBee Code from HCDE 439 Lecture
// Attribution: player_simple.ino by ladyada
//https://github.com/adafruit/Adafruit_VS1053_Library/blob/
//master/examples/player_simple/player_simple.ino
​
#include <Button.h>
#include <SoftwareSerial.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
#include <SPI.h>
​
const String myNodeName = "Room Board 2";
const byte TAB_CHAR = 0x09;
const byte NEWLINE_CHAR = 0x0A;
const int MAX_FIELDS = 4;
//SoftwareSerial xBee(14, 15);
String msg = "";
Button camButt(7, INPUT);
int code;
​
// These are the pins used for the breakout example
#define BREAKOUT_RESET 9 // VS1053 reset pin (output)
#define BREAKOUT_CS 10 // VS1053 chip select pin (output)
#define BREAKOUT_DCS 8
//// These are the pins used for the music maker shield
//#define SHIELD_RESET -1 // VS1053 reset pin (unused!)
//#define SHIELD_CS 7 // VS1053 chip select pin
//#define SHIELD_DCS 3
// These are common pins between breakout and shield
#define CARDCS 53 // Card chip select pin
// DREQ should be an Int pin, see
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(BREAKOUT_RESET,
BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);
void setup() {
Serial.begin(38400);
Serial3.begin(38400);
Serial.println("\n\nxBeeSendReceiveMsg");
if (! musicPlayer.begin()) { // initialise the music player
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
while (1);
}
Serial.println(F("VS1053 found"));
if (!SD.begin(CARDCS)) {
Serial.println(F("SD failed, or not present"));
while (1); // don't do anything more
}
​
// list files
printDirectory(SD.open("/"), 0);
// Set volume for left, right channels. lower numbers ==
//louder volume!
musicPlayer.setVolume(10,10);
musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);
}
​
void loop() {
String msg = checkMessageReceived();
if (msg.length() > 0) {
Serial.println(msg);
}
String msgFields[MAX_FIELDS];
for (int i = 0; i < MAX_FIELDS; i++) {
msgFields[i] = "";
}
int fieldsFound = 0;
String buf = "";
for (int i = 0; i < msg.length(); i++) {
if (((msg.charAt(i) == TAB_CHAR) ||
(msg.charAt(i) == NEWLINE_CHAR)) &&
(fieldsFound < MAX_FIELDS)) {
msgFields[fieldsFound] = buf;
buf = "";
fieldsFound++;
}
else {
buf += msg.charAt(i);
}
}
int camAction = camButt.checkButtonAction();
if(camAction == Button::CLICKED) {
code = 4444;
String msg = myNodeName + "\t" + code + "\n";
Serial.print(msg);
Serial3.print(msg);
}
for (int i = 0; i < fieldsFound; i++) {
Serial.println(msgFields[i]);
}
int aNumber = msgFields[1].toInt();
int scrPower = msgFields[2].toInt();
​
switch (aNumber) {
case 2100:
if (scrPower > 0 && scrPower <25) {
Serial.println(F("Scream1"));
musicPlayer.setVolume(20,20);
musicPlayer.playFullFile("Scream~1.mp3");
} else if (scrPower >= 25 && scrPower <50) {
Serial.println(F("Scream2"));
musicPlayer.setVolume(15,15);
musicPlayer.startPlayingFile("Scream~1.mp3");
} else if (scrPower >= 50 && scrPower <75) {
Serial.println(F("Scream3"));
musicPlayer.setVolume(10,10);
musicPlayer.startPlayingFile("Scream~1.mp3");
} else if (scrPower >= 75) {
Serial.println(F("Scream4"));
musicPlayer.setVolume(5,5);
musicPlayer.startPlayingFile("Scream~1.mp3");
}
break;
case 9999:
musicPlayer.stopPlaying();
break;
}
}
Arduino 3: Camera Module
// Attribution: Adafruit_VC0706 - Snapshot
// https://learn.adafruit.com/ttl-serial-camera/using-the-camera
#include <Button.h>
#include <SoftwareSerial.h>
#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>
#define chipSelect 10
File imgFile;
int x = 0;
Button btn(7, INPUT_PULLUP);
#if ARDUINO >= 100
SoftwareSerial cameraconnection = SoftwareSerial(2, 3);
#else
NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif
​
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
​
void setup() {
#if !defined(SOFTWARE_SPI)
#if defined(__AVR_ATmega1280__) ||
defined(__AVR_ATmega2560__)
if(chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega
#else
if(chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc.
#endif
#endif
Serial.begin(38400);
// declare default CS pin as OUTPUT
pinMode(8, OUTPUT);
if (!SD.begin(6)) {
Serial.println("Card failed, or not present");
return;
}
// Try to locate the camera
if (cam.begin()) {
Serial.println("Camera Found:");
} else {
Serial.println("No camera found?");
return;
}
// Print out the camera version information (optional)
char *reply = cam.getVersion();
if (reply == 0) {
Serial.print("Failed to get version");
} else {
Serial.println("-----------------");
Serial.print(reply);
Serial.println("-----------------");
}
// Set the picture size - you can choose one of 640x480,
//320x240 or 160x120
// Remember that bigger pictures take longer to transmit!
cam.setImageSize(VC0706_160x120);
uint8_t imgsize = cam.getImageSize();
Serial.print("Image size: ");
if (imgsize == VC0706_640x480) Serial.println("640x480");
if (imgsize == VC0706_320x240) Serial.println("320x240");
if (imgsize == VC0706_160x120) Serial.println("160x120");
Serial.println("Snap...");
if (! cam.takePicture())
Serial.println("Failed to snap!");
else
Serial.println("Picture taken!");
// Create an image with the name IMAGExx.JPG
char filename[13];
strcpy(filename, "IMAGE00.JPG");
for (int i = 0; i < 100; i++) {
filename[5] = '0' + i/10;
filename[6] = '0' + i%10;
if (! SD.exists(filename)) {
break;
}
}
// Open the file for writing
imgFile = SD.open(filename, FILE_WRITE);
// Get the size of the image (frame) taken
uint16_t jpglen = cam.frameLength();
Serial.print("Storing ");
Serial.print(jpglen, DEC);
Serial.print(" byte image.");
int32_t time = millis();
pinMode(8, OUTPUT);
// Read all the data up to # bytes!
byte wCount = 0; // For counting # of writes
while (jpglen > 0) {
// read 32 bytes at a time;
uint8_t *buffer;
uint8_t bytesToRead = min(32, jpglen);
buffer = cam.readPicture(bytesToRead);
imgFile.write(buffer, bytesToRead);
if(++wCount >= 64) {
Serial.print('.');
wCount = 0;
}
jpglen -= bytesToRead;
}
imgFile.close();
time = millis() - time;
Serial.println("done!");
Serial.print(time); Serial.println(" ms elapsed");
imgFile = SD.open(filename);
if (imgFile)
{
Serial.println("Prepare file");
Serial.println("Image Start");
while (imgFile.available())
{
x = imgFile.read();
Serial.print(x);
Serial.println("");
}
// close the file:
imgFile.close();
Serial.println("Image End");
} else
{
// if the file didn't open, report an error:
//Serial.println("error opening the text file!");
}
}
void loop()
{
}
Python: Camera Module
# Attribution: Storing String From Arduino To Text File Using #Python https://stackoverflow.com/questions/20892133/storing-#string-from-arduino-to-text-file-using-python
​
import serial
import os
ser = serial.Serial('/dev/cu.usbmodem1421', 38400)
os.chdir('/Users/me/Desktop/Monsters_Inc_Leaderboard')
myFile = open('latest_scarer.jpg', 'w')
stop = False
while True:
x = ser.readline()
line = x.strip('\n')
line = line.strip('\r')
if line in "Image Start":
print x
while stop is not True:
x = ser.readline()
line = x.strip('\n')
line = line.strip('\r')
if line in "Image End":
print x
stop = True
else:
x = int(x)
char = chr(x)
print char
myFile.write(char)
myFile.flush()
myFile.close()
else:
print x
ser.close()
Process and Implementation
Gallery
Successful attempt at taking a photo using Spinel JPEG TTL Camera Module for Arduino. A python code was run through the terminal that took the photo from the SD Card module on the Arduino board and wrote it as a JPEG file into a folder on a laptop. A button is then pressed to tell the Command Center (Mission Control) to use that photo on the leaderboard.
Laser cut acrylic door frame
Laser cut door
Testing camera module at Starbucks
Laser cut acrylic door frame
Developing the System:
Showcasing Final Prototype:
Final assembly of project at HCDE showcase
User testing at showcase
Scare room image
Final assembly of project at HCDE showcase
The actual implementation of our system required a combination of hardware and software. Ultimately, this project was very successful and we accomplished our stretch goals. We met many challenges along the way though, which really helped us develop our understanding of working with Arduinos, especially through all of the things we found that did not work.
Description of the Enclosure
Our enclosure is an elevated structure that constitutes the child’s room and leaves room below to account for the game play. There are two 3D-printed characters, Mike and Sully, who are resting on top of joysticks, with the handles then extending beneath the floor of the structure. The structure itself has a track in the floor that allows the characters and their joysticks to be pushed through the game as the user maneuvers the handle of the joystick through it.
Entering the Enclosure
To enter the enclosure and have the opportunity to play the game, the door at the front must first be opened. For the door to even be accessed, our system must receive a Xbee message from Mission Control that occurs after they have received the character’s name from Remote Site 1 and then pressed a button telling us to activate our system. The light in the door turns on as a result of receiving this message and a welcome message is displayed on the LCD display telling the selected character to press a button and enter. The user then chooses the character they want to play with by pressing the button for that character (each button is connected to a joystick), which opens the door and gives them five seconds to maneuver their character through the door and into the room. A servo motor opens the door and then closes it after the five seconds is over. This button is now the only one activated, and so pressing the other character’s button will do nothing.
Game Play
The user moves the character through the track, closer to the child’s bed in the corner. When they have reached a certain point, the motion sensor (located below the enclosure) detects the user’s hand and activates the actual game. The instructions are briefly listed on the LCD display, but essentially the goal is for the user to press the button as many times as possible to receive a higher scare power. A timer for 15 seconds begins, which allows the user to start pressing the button. Once the time is up, the scare power is displayed on the LCD display and a XBee message is sent out both to our second Arduino (with the MP3 Component) and Remote Site 1. This message is intended to tell the MP3 player the scare power, so that it can play the scream for that score. There are four different screams that can be outputted, each based on a different range of values received. Remote Site 1 uses this message to begin listening for the scream with their sound sensor. The door opens once the game is over and the LCD display tells the user to leave. When the user presses the button, the door will shut again.
Camera Use
At the conclusion of the scare game, a facilitator of the game is expected to run the Python code on the same computer being used for Mission Control. This will take a picture of the scarer and save it to a folder on the computer’s desktop. The facilitator is then expected to press a button that will send Mission Control a XBee message telling them to update the scarer picture in the folder, now that the new picture has been saved. We initially intended to have the pictures taken automatically, but due to some challenges we will mention later, the camera requires the facilitator to manually run it.
Contamination Warning
An important message that we send to both of the other groups is Contamination (or message 2319 as it is called in the movie). Contamination is meant to convey that something went wrong in the process and that the game should automatically be ended and alerts sent out. Our system reacts to this command by flashing the LED in the door, turning on a laser that points across the enclosure, and opening the door to make the character leave. The contamination actions are ended when we receive a message from Mission Control, saying that it is all clear.
Successes
Our initial plan contained two main stretch goals: gamification of the system and the implementation of the camera. We accomplished both of these and made an enclosure that was well-designed and exciting. Users at the showcase seemed excited by the overall design of the system, and the opportunity to play with either Mike or Sully. The extra attention put into these details was important to the general feel and portrayal of our system. It was easily recognizable as Monster’s Inc. with the 3D printed characters and the laser cut version of Boo’s door from the movie. The gamification really added to the system too, because people were actually able to play with and see the effect that it had on the other sites.
Challenges: The Camera
The camera was extremely difficult to work with, and we experienced many difficulties in the different stages of implementation. The goal was to have the camera take a picture after receiving a XBee message and then somehow get the picture onto the leadership board that was created through Processing, likely through some sort of XBee message. While the wiring initially didn’t seem that complicated, we had some problems setting it up, especially when it came to adding a component with an SD card. At this point, we were using an Arduino Mega instead of an Arduino Uno because we needed more pins to wire all of these pieces. The original intention was to use a MicroSD Card Breakout Board, but we eventually changed course because the part was being extraordinarily finicky and detrimental to our completion of this stage of the project. After that, we had the idea to just use the SD card in the VS1053 Codec that was acting as our MP3 player. This was successful and we were finally able to move on to trying to get the actual code to work.
Taking a picture and saving it to the SD card was pretty easy to figure out, since there was existing code, but we weren’t entirely sure that sending an image over XBee was even possible. After multiple failures at getting this to work, we began researching other techniques we could use. Eventually, we landed on using Python to save the image to a folder on the laptop that was running Mission Control so that the Processing code could just replace the image with the new one in the folder when prompted. Experimentation led to this method actually working, but then we ran into another issue: the XBee. We hadn’t been testing the camera in conjunction with the XBee as we were trying to focus on one part at a time, but at this point, we were trying to integrate the camera, MP3, and XBee code, as we knew that each part worked individually. Unfortunately, we couldn’t get the camera to work properly when combined with the XBee (it worked perfectly with the MP3 player), likely due to some sort of interference in the messages being sent.
So, we had each part working individually, but obviously the system needed all of the parts to function together. As we were running out of time and couldn’t figure out a way to solve this problem, we separated the components: the MP3 player and XBee went with the Arduino Mega and the camera with another Arduino Uno. This is how we finally ended up with three Arduinos for Remote Site 2. By adding a button and making slight adjustments to the Processing code, we made it so that the camera code would be run manually on the laptop, and then the button connected to the Arduino Mega would be pressed after it saved the image to the folder. The XBee on this Arduino would also send the message to the Arduino connected to Processing, saying that the image should be updated.
​
Attributions
Mike 3D Print: Mike Wazowski ringstand (From Disney Pixar's Monsters Inc.) by HisashilMAI
https://www.thingiverse.com/thing:697835
​
Sully 3D Print: Sully (Monsters inc.) by Gunnar86
https://www.thingiverse.com/thing:2213823
​
Camera & Comm Tool General Testing Info
https://learn.adafruit.com/ttl-serial-camera/using-comm-tool
​
Camera Code
https://github.com/adafruit/Adafruit-VC0706-Serial-Camera-Library
https://learn.adafruit.com/ttl-serial-camera/overview
https://forums.adafruit.com/viewtopic.php?f=22&t=53711
http://www.elecfreaks.com/7861.html
https://www.itead.cc/wiki/VC0706_UART_Camera_%EF%BC%88Supports_JPEG%EF%BC%89