top of page

IMPLEMENTATION

System Diagram:
Implementation:
​

The house features servo motors running blinds that open and close in response to light, as detected by a photocell receptor, a rope swing that brings people up to the house from the base of the tree, also powered by a servo motor, an LCD display, and an alert system. To control the rope swing there is a main button in the house that can lower or raise the swing when pressed. The rope swing is guided by a continuous servo motor.  At the base of the tree there is another button that acts as a doorbell by sounding a peizo buzzer in the house when pressed. Also at the base of the Trome there are two white LED lights that light the area around the rope swing. When alerts are transmitted through the Xbee wireless transmitter the base LEDs blink rapidly, before responding to the alert.

The alert system is made up of a red, blue, and green LED lights in the home that light up and respond to various disaster alerts. During disaster alerts the main LCD screen in the home displays alert information and advises the occupants on how to respond. When there are no disasters the LCD displays the state of the house, and other information like time, from a real time clock (RTC), and temperature, from a temperature sensor in the home.


The home mainly responds to the fire, zombie, burglary, and cute animals alerts. In the situation of a fire alert the buzzer sounds an alarm, the red LED flashes and the LCD gives instruction on how to evacuate, by displaying the words “Fire dept notified. Evacuate Trome”. In both the burglary and zombie scenarios the rope swing will come up if it is down and the blinds will close, controlled by the three servo motors. If the alert is a zombie alert, the green LED will flash, but the buzzer will not sound, because we do not want the house to alert the zombies to its presence. The LCD will print out “Zombies in area: Stay inside the Trome”.  Additionally, for a zombie alert the white LEDs at the base of the tree will turn off, so that the zombies think that the home is empty. For a burglary alert, the blue LED will flash and the buzzer will sound. The LCD will print out “Burglary in area. Trome engaged in safe mode”.  Also, the white LEDS at the base of the tree will turn on, in order to let potential burglars know that there are occupants in the home.  Lastly, for cute animal alerts, the rope swing will be lowered by the continuous servo motor, so that the occupants can have access to the cute animals. Neither the LED display or the buzzer will react, because the cute animal alert is not an emergency alert. However, the LCD will print out “Cute animals detected: Brace for cuteness overload”, so that the occupants will be aware that there are cute animals in the area.

​

Software:

 

We initialized and defined all of the libraries and  hardware components of the Trome at the beginning of our code.  Additionally, the positions of each of the servo motors were initialized before our setup, loop, and written methods. During the setup method, we attached each of the servo motors and coded the input or output of each of the buttons, the buzzer, and the LEDs. Each of the LEDs were color coded in order to keep the LEDs straight while coding. Additionally, the serial monitor, LCD display, and real time clock were all begin within the setup method. While there is not an alert, the loop method runs through the methods for the LCD display and light sensor. Additionally, when there is not an alert the loop method contains if statements that process the functionality of the doorbell system. These if methods pull buzzer code from two song methods located at the end of the loop method.  Additionally, within the alert method, is the code for when an alert is received. These alerts are written through if and else if statements that respond to different wirelessly transmitted alerts. Each of the alerts utilizes a separate LCD scroll method in order to have the LCD for each of the alerts properly scroll. If the alert requires the rope swing or the blinds, the alert will call upon a separate method, utilizing an if statement which recognizes the current status of the rope swing or blinds and responds appropriately. Outside of the loop method at the end of the code.  We wrote a total of twelve void methods and five int methods in order to support the functionality of the house. These methods include the supporting for code for the real time clock, LCD scroll, sensors, buzzer noises, and servo motors.

 

From what we know, we did not word for word copy any piece of code, apart from the Smart City code written by HCDE professor Andrew Davidson. Rather, we took inspiration and pieces of code and modified it to fit our needs. Thus, our attributions and inspirations list is commented out at the top of our code.

​

Code:

/*

Attribution and Inspiration from:

Andy Davidson - SmartCityNode 05/2016

https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/downloads

https://www.youtube.com/playlist?list=PLijVDrW1XSPvqYRcKcF-4_r9YuuZLUNsw

https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/wiring-it-up

https://www.arduino.cc/en/Reference/ServoWrite

https://www.arduino.cc/en/Reference/Servo

https://www.parallax.com/product/900-00008

https://jeroendoggen.wordpress.com/2013/03/13/arduino-library-for-the-parallax-futaba-continuous-rotation-servo/

https://www.parallax.com/sites/default/files/downloads/900-00008-Continuous-Rotation-Servo-Documentation-v2.2.pdf

https://learn.adafruit.com/i2c-spi-lcd-backpack/overview

https://learn.adafruit.com/xbee-radios/overview

https://learn.adafruit.com/xbee-radios/overview

https://learn.adafruit.com/tmp36-temperature-sensor/using-a-temp-sensor

http://www.instructables.com/id/How-to-make-flashing-police-lights-with-sound/step3/The-code/

https://www.arduino.cc/en/Reference/Tone

Alessandro Spallina

email: alessandrospallina1@gmail.com

website: aleksnote.altervista.org

 

https://www.arduino.cc/en/Tutorial/ToneMelody?from=Tutorial.Ton

https://www.arduino.cc/en/Tutorial/Button

*/

​

// Two libraries for the SmartCity and XBee message stuff

#include <SoftwareSerial.h>

#include <SmartCityNodeLib.h>

 

//LCD Library

#include "Adafruit_LiquidCrystal.h"

 

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib

#include "Wire.h"

#include "RTClib.h"

 

#if defined(ARDUINO_ARCH_SAMD)

// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!

  #define Serial SerialUSB

#endif

//Real time clock for setting the current time and day

RTC_DS1307 rtc;

 

char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"};

 

// Connect via i2c, default address #0 (A0-A2 not jumpered)

Adafruit_LiquidCrystal lcd(0);

 

//Time library

#include <Time.h>  

#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by Unix time_t as ten ASCII digits

#define TIME_HEADER  'T'   // Header tag for serial time sync message

#define TIME_REQUEST  7    // ASCII bell character requests a time sync message

// T1262347200  //noon Jan 1 2010

 

//Servo libraries

#include <Servo.h>

#include <ContinuousRotationServo.h>

 

// create servo object to control a servo

Servo windowOne;  

Servo windowTwo;

Servo myservo;

ContinuousRotationServo Servo;

int distance;

 

int pos = 0;    // variable to store the servo position

 

int baseLights = 13; //base lights at base of tree

 

const int baseButton = 4; //base of tree button

const int topButton = 5; //top of tree button

 

int baseButtonState = 0; //variable for reading the pushbutton

int topButtonState = 0;

 

int swingState = 0;

 

int blindState = 0; // 0 means closed, 1 means open

 

int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to

 

int photocellPin = 1;  // the cell and 10K pulldown are connected to a1

int photocellReading;   // the analog reading from the sensor divider

 

int buzzpin = 9; //piezo buzzer

 

int fireLed = 8; //redLED

 

int blueLed = 7; //blueLED

 

int greenLed= 6; //greenLED

 

// some constants to identify my node to the library object

const String myNodeName = "Trome";

const int    myZone = SmartCityNode::RESIDENTIAL;  // declare what zone you are

 

// because every Arduino program has to blink an LED

const int ledPin = LED_BUILTIN;  // pin 13, no doubt


 

// this connects your program to your XBee module

// you must use pin 2 for RX and pin 3 for TX

// the XBee must be set to 9600 baud

SmartCityNode myNode;

 

// state variables

boolean myDebugging = true;

 

char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };

int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };

 

void setup() {

 // just for our own debugging

 Serial.begin(9600);

 Serial.println("\n\n*** Starting SmartCityNode demo");

 

 windowOne.attach(10);

 windowTwo.attach(11);

 

 myservo.attach(12);  // attaches the servo on pin 12 to the servo object

 

 pinMode(baseButton, INPUT);

 pinMode(topButton, INPUT);

 pinMode(buzzpin, OUTPUT);

 

 pinMode(fireLed, OUTPUT);

 pinMode(blueLed, OUTPUT);

 pinMode(greenLed, OUTPUT);

 

 // comment this line out to suppress debugging messages from the library

 myNode.setDebugOn();

 

 // this starts up your XBee and does other SmartCity initialization stuff.

 // the second argument is just to identify your node by a name.

 // you must declare what zone your node is in so that you only receive alerts

 // targeted for that zone. to do that, use one of these codes for the first

 // argument:

 //       SmartCityNode::RESIDENTIAL

 //       SmartCityNode::BUSINESS

 //       SmartCityNode::INDUSTRIAL

 

 myNode.begin(myZone, myNodeName);

 

 // set up the LCD's number of rows and columns:

 lcd.begin(16, 2);

 

 #ifndef ESP8266

 while (!Serial);

 #endif

 

 Serial.begin(9600);

 if (! rtc.begin()) {

   Serial.println("Couldn't find RTC");

   while (1);

 }

 

 if (! rtc.isrunning()) {

   Serial.println("RTC is NOT running!");

   // following line sets the RTC to the date & time this sketch was compiled

   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

   // This line sets the RTC with an explicit date & time, for example to set

   // January 21, 2014 at 3am you would call:

   // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

 }

}

 

void loop() {

 // check for an incoming alert

 // alertReceived() returns 0 (zero) if none have been sent to your zone.

 // it returns a code as follows if there is one:

 //       SmartCityNode::FIRE

 //       SmartCityNode::GAS

 //       SmartCityNode::FLOOD

 //       SmartCityNode::BURGLARY

 //       SmartCityNode::EARTHQUAKE

 //       SmartCityNode::ZOMBIE

 //       SmartCityNode::CONTAINMENT_BREACH

 //       SmartCityNode::HIPSTER_INVASION

 //       SmartCityNode::UNWANTED_SOLICITORS

 //       SmartCityNode::BLACK_FRIDAY

 //       SmartCityNode::CUTE_ANIMALS

 //       SmartCityNode::APOCALYPSE

 

 //prints Welcome message, current time, and current temp on LCD

 realTimeClock();

 

 //senses the light level and responds by moving the curtains

 blindState = lightSensor();

 

 //turn base lights on

 digitalWrite(ledPin, HIGH);

 

 baseButtonState = digitalRead(baseButton); //base of tree button

 topButtonState = digitalRead(topButton); //top of tree button

 

// if base button is pushed ring doorbell, if top button is pushed raise/lower the swing 

 if (baseButtonState == HIGH) {

   twinkle();

 }

 if (topButtonState == HIGH) {

   if (swingState == 0) {

     swingState = raiseSwing();

   }

   else if (swingState = 1) {

     swingState = lowerSwing();

   }

 }

 

 int alert = myNode.alertReceived();

 if (alert != 0) {

   

   digitalWrite(ledPin, HIGH);

 

   Serial.print("*** alert received at ");

   float sec = millis() / 1000.0;

   Serial.print(sec);

   Serial.print(": ");

   Serial.print(alert);

   Serial.print(" (");

   Serial.print(myNode.alertName(alert));

   Serial.println(")");

   

   if (alert == SmartCityNode::FIRE) {

     Serial.println("Fire dept notified. Evacuate Trome");

     lcd.setCursor(0,0);

     lcd.print("Fire dept notified.");

     lcd.setCursor(0,1);

     lcd.print("Evacuate Trome");

     buzz(50);

     digitalWrite(fireLed, HIGH);   // turn the LED on (HIGH is the voltage level)

     delay(500);              // wait for a second

     digitalWrite(fireLed, LOW);   // turn the LED off by making the voltage LOW

     delay(500);   // wait for a second

     for (int positionCounter = 0; positionCounter < 35; positionCounter++) {

       lcdScroll();

     }

   }

   else if (alert == SmartCityNode::BURGLARY) {

     Serial.println("Burglary in area. Trome engaged in safe mode");

     //swingDown();

     lcd.setCursor(0,0);

     lcd.print("Burglary in area. Remain calm");

     lcd.setCursor(0,1);

     lcd.print("Trome engaged in safe mode");

     tone(buzzpin,2000, 2000);

     digitalWrite(blueLed, HIGH);   // turn the LED on (HIGH is the voltage level)

     digitalWrite(baseLights, HIGH);

     for (int positionCounter = 0; positionCounter < 35; positionCounter++) {

       lcdScroll();

     }

     if (blindState = 1) {

       blindState = closeBlinds();

     }

     if (swingState == 0) {

       swingState = raiseSwing();

     }

   }

   

   else if (alert == SmartCityNode::ZOMBIE) {

     digitalWrite(greenLed, HIGH);

     Serial.println("Zombies in area: Stay inside the Trome.");

     lcd.setCursor(0,0);

     lcd.print("Zombies in area");

     lcd.setCursor(0,1);

     lcd.print("Stay inside Trome");

     for (int positionCounter = 0; positionCounter < 40; positionCounter++) {

     lcdScroll();

     }

     if (blindState = 1) {

       blindState = closeBlinds();

     }

     if (swingState == 0) {

       swingState = raiseSwing();

     }

     digitalWrite(greenLed, LOW);

   }

   

   else if (alert == SmartCityNode::HIPSTER_INVASION) {

     Serial.println("Hipsters detected: Stay inside the Trome.");

     lcd.setCursor(0,0);

     lcd.print("Hipsters detected");

     lcd.setCursor(0,1);

     lcd.print("Stay inside Trome");

     for (int positionCounter = 0; positionCounter < 40;     positionCounter++) {

     lcdScroll();

     }

     if (blindState = 1) {

       blindState = closeBlinds();

     }

     if (swingState == 0) {

     swingState = raiseSwing();

     }

   } else if (alert == SmartCityNode::CUTE_ANIMALS) {

     Serial.println("Cute animals detected: Brace for cuteness overload.");

     lcd.setCursor(0,0);

     lcd.print("Cute animals detected");

     lcd.setCursor(0,1);

     lcd.print("Brace for cuteness overload");

     for (int positionCounter = 0; positionCounter < 40; positionCounter++) {

     lcdScroll();

     }

     if (swingState == 1) {

     swingState = lowerSwing();

     }

   }

}

}

 

void digitalClockDisplay(){

 // digital clock display of the time

 Serial.print(hour());

 printDigits(minute());

 printDigits(second());

 Serial.print(" ");

 Serial.print(day());

 Serial.print(" ");

 Serial.print(month());

 Serial.print(" ");

 Serial.print(year());

 Serial.println();

}


 

void printDigits(int digits){

 // utility function for digital clock display: prints preceding colon and leading 0

 Serial.print(":");

 if(digits < 10)

   Serial.print('0');

 Serial.print(digits);

}

 

void processSyncMessage() {

 // if time sync available from serial port, update time and return true

 while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of header & 10 ASCII digits

   char c = Serial.read() ;

   Serial.print(c);  

   if( c == TIME_HEADER ) {       

     time_t pctime = 0;

     for(int i=0; i < TIME_MSG_LEN -1; i++){   

       c = Serial.read();          

       if( c >= '0' && c <= '9'){   

         pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    

       }

     }   

     setTime(pctime);   // Sync Arduino clock to the time received on the serial port

   }  

 }

}

void logAlert (String myName, int zone, int alert) {

 // just blink the led and write a message out to the serial monitor

 digitalWrite(ledPin, HIGH);

 Serial.print("*** alert received at ");

 float sec = millis() / 1000.0;

 Serial.println(sec);

 Serial.print("***   node = ^");

 Serial.print(myName);

 Serial.print("^ in zone # ");

 Serial.print(zone);

 Serial.print(": ");

 Serial.println(myNode.zoneName(zone));

 Serial.print("***   alert = ");

 Serial.print(alert);

 Serial.print(": ");

 Serial.println(myNode.alertName(alert));

 

 // end of the blink

 digitalWrite(ledPin, LOW);

}

 

void lcdScroll (){

 lcd.setCursor(16,1); // set the cursor outside the display count

 lcd.autoscroll();    // set the display to automatically scroll:

 lcd.print(" ");      // print empty character

 delay(500);          

}

 

void tempF () {

//getting the voltage reading from the temperature sensor

 int reading = analogRead(sensorPin);  

 

// converting that reading to voltage, for 3.3v arduino use 3.3

float voltage = reading * 5.0;

voltage /= 1024.0;

 

// now print out the temperature

float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset

                                               

// now convert to Fahrenheit

float temperatureF = ((temperatureC * 9.0 / 5.0) + 32.0);

Serial.print(temperatureF); Serial.println(" degrees F");

lcd.print(temperatureF);

lcd.print( " F ");

}

 

void realTimeClock() {

   DateTime now = rtc.now();

   lcd.setCursor(0,0);

   lcd.print("Welcome to your safe Trome :)");

   Serial.print("Welcome to your safe Trome :)");

   lcd.setCursor(0,1);

   lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);

   lcd.print(" ");

   Serial.println();

   Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);

   Serial.print(" ");

   lcd.print(now.month(), DEC);

   lcd.print('/');

   Serial.print(now.month(), DEC);

   Serial.print('/');

   lcd.print(now.day(), DEC);

   lcd.print('/');

   Serial.print(now.day(), DEC);

   Serial.print('/');

   lcd.print(now.year(), DEC);

   Serial.print(now.year(), DEC);

   Serial.print('/');

   lcd.print(" ");

   lcd.print(now.hour(), DEC);

   lcd.print(':');

   Serial.print(" ");

   Serial.print(now.hour(), DEC);

   Serial.print(':');

   lcd.print(now.minute(), DEC);

   lcd.print(':');

   Serial.print(now.minute(), DEC);

   Serial.print(':');

   lcd.print(now.second(), DEC);

   Serial.print(now.second(), DEC);

   Serial.println();

   //print temp

   lcd.print(" ");

   tempF();

   //Serial.println(tempF());

   for (int positionCounter = 0; positionCounter < 45; positionCounter++) {

       lcdScroll();

     }

}

 

int lightSensor() {

 photocellReading = analogRead(photocellPin);  

 Serial.print("Light Level = ");

 //for the purpose of demonstrating our alert system,

 //the required photo cell reading for bright light has been changed from 500 to 960 to account for the bright lighting in our testing room

 if (photocellReading < 960) {

   Serial.print("Dim , Analog Reading =  ");

   //Keep curtains open

   Serial.println(photocellReading);     // the raw analog reading

   if (blindState = 0) {

Serial.println("Opening Curtains");

     blindState = openBlinds();

     Return 1;

   }

 }

 

 else {

   Serial.print("Bright , Analog Reading = ");

   Serial.println(photocellReading);     // the raw analog reading

   //Close curtains

   if (blindState = 1) {

       Serial.println("Closing Curtains");

       blindState = closeBlinds();

  return 0;  

   }

}

}

 

void buzz(unsigned char time){

 analogWrite(buzzpin,170);

 tone(buzzpin, 1000, 1000);

 delay(time);

 analogWrite(buzzpin,0);

 delay(time);

}

int openBlinds() {

 for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees

   // in steps of 1 degree

   windowOne.write(pos); // tell servo to go to position in variable 'pos'

   windowTwo.write(pos);

   delay(15); // waits 5ms for the servo to reach the position

 }

 return 1;

}

int closeBlinds() {

 for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees

   windowOne.write(pos); // tell servo to go to position in variable 'pos'

   windowTwo.write(pos);

   delay(15);  // waits 5ms for the servo to reach the position

 }

 return 0;

}

 

int lowerSwing () { //the swing is at the top of the tree

   Serial.println("Lowering Swing");

   myservo.write(0);

   delay(8000);

   myservo.write(92);

   

  return 0;

}

 

int raiseSwing() { //the swing is at the bottom of the tree

   Serial.println("Raising Swing");

   //Cont. code for raising the swing

   myservo.write(180);

   delay(8000);

   myservo.write(92);

    return 1;

}

void playTone(int tone, int duration) {

 for (long i = 0; i < duration * 1000L; i += tone * 2) {

   digitalWrite(buzzpin, HIGH);

   delayMicroseconds(tone);

   digitalWrite(buzzpin, LOW);

   delayMicroseconds(tone);

  }

}

void playNote(char note, int duration){

 int i;

 for(i=0; i<8; i++)

 {

   if(names[i]==note)

     playTone(tones[i], duration);

 }

}

 

void twinkle(){ //Twinkle Twinkle Little Star tune

 int i;

 int length = 27;

 char notes[] = "edcdeeedddeeeedcdeeeeddedc";

 int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1};

 int tempo = 200;  

 for(i=0;i<length;i++){

   if(notes[i]==' ') {

     delay(beats[i]*tempo);

    else

     playNote(notes[i], beats[i]*tempo);

 delay(tempo / 2);

 }

}

Breadboard Layout:
bottom of page